| 18 Feb 2026 | |||
| timo | uhhh I thought there's an ID? | 14:01 | |
| for breakpoint hit notifications it uses the ID of your breakpoint set request | 14:02 | ||
| StepCompleted behaves similarly | 14:03 | ||
| thread list response should also use the id from the thread list request | |||
| patrickb | I can correlate the response to the request. | 14:04 | |
| timo | oh, you mean from one response to another things can change, and then after the response things can change further? | ||
| you never know when the results from some request get invalidated? | 14:05 | ||
| patrickb | Yes. Specifically when I asynchronously receive two responses (e.g. a frame dump and a break point notification also containing a frame dump) and they disagree I can't know which one is fresh. | 14:09 | |
| If they had an absolute ordering, I could discard any chunk of data for which I already received a state with a higher order no. | 14:10 | ||
| Or is there already an ordering guarantee simply by the order in which I receive the events over the wire? | 14:11 | ||
| (Not entirely sure, but I think I've seen that not be the case. Test scenario was: Suspend_all, set_breakpoint, resume_all, thread_list, breakpoint_hit_response, thread_list_response (this last thread_list_response has the broken thread still as running)) | 14:13 | ||
| timo | hm. a thread can only have its stack trace dumped when it's suspended, and access to sending on the socket is mutexed | ||
| by broken thread you mean suspended? | |||
| patrickb | yes | ||
| gets suspendend by the breakpoint | |||
| timo | here's where MDS_PROTOCOL may be actually insightful | 14:14 | |
| btw do you keep all these tests you do around in a relatively easy-to-reproduce form? would be great to get more tests for the debugserver feature | 14:17 | ||
| patrickb | Maybe. But I strongly suspect it's an undefinedness in the protocol itself. | ||
| I don't. This is on the go stuff happening while I click around in the UI :-P | 14:18 | ||
| timo | aw | 14:19 | |
| did you see the test cases in the MoarVM::Remote module? | |||
| I've built a little "interpreter" for test scenarios | 14:20 | ||
| patrickb | I didn't yet. I'll have a look. | ||
| Are thread IDs immutable? | 14:21 | ||
| timo | I believe we dole them out from a central counter when a thread is created and don't change them afterwards | 14:22 | |
| patrickb | cool | ||
| patrickb learned a new word | 14:23 | ||
| timo | > child_tc->thread_id = 1 + MVM_incr(&tc->instance->next_user_thread_id); | ||
| patrickb | probably unrelated, but github.com/MoarVM/MoarVM/blob/main...ver.c#L711 this MVM_cas looks wrongly used (it doesn't compare to the old value) | 14:47 | |
| timo | oh, I think you're right | 15:41 | |
| patrickb | github.com/MoarVM/MoarVM/blob/main...ate.c#L260 <- Is this safe? (it doesn't validate if the swap worked) | 15:45 | |
| The thread that refuses to step has a gc_status of 15, i.e. 00001111, i.e. SUSPENDED|SUSPEND_REQUEST|STOLEN | 15:46 | ||
| timo | > 13 years ago | ||
| > full code audit of all atomics usage | |||
| stollen! but it's not anywhere near christmas! | |||
| patrickb | wait, is stolen meant to be a superset of unable? | 15:48 | |
| timo | i'm thinking when a thread suspends it should be clearing its suspend request, but "stolen" is what happens when a thread is blocked when a GC run starts, so it wouldn't have done the state transition itself | ||
| patrickb | I.e. can STOLEN be treated as UNABLE? | 15:49 | |
| timo | yeah, "mark thread blocked" sets "unable", when a GC run then starts the orchestrator thread will transition it to "stolen" | ||
| with just a very quick think, yes | 15:50 | ||
| patrickb | Hm. Still fishy. How can it end up with SUSPENDED|SUSPEND_REQUEST? Also why doesn't the STOLEN turn back to UNABLE after the GC finishes? | 15:55 | |
| It's pretty repeatable btw... | |||
| Ow. SUSPEND_REQUEST = 12, SUSPENDED = 4, so SUSPEND_REQUEST is actually a superset of SUSPENDED. | 15:57 | ||
| timo | you have to mask it out | 15:58 | |
| I think the two cas that don't check the result value could very well be the problem, they don't take suspend requesds into account at all | 15:59 | ||
| so if the stolen thread has the request bit set or is even marked suspended, it wouldn't go back to unable, then it can't resume itself properly when mark_thread_unblocked happens | |||
| does that sound about right? | |||
| patrickb | Sounds about right. Is there some reason that code in question can safely assume it can change that field unchecked? | 16:05 | |
| timo | it's the orchestrator thread, all other threads are assumed to not be doing anything at that point | ||
| patrickb | But the debugger thread still can? | 16:06 | |
| So got the assumption broken by the introduction of the debugger thread? | |||
| timo | ah, yeah | 16:07 | |
| patrickb | A first quick change seems to make it work. | 16:47 | |