’ start the pre-emptive workers from a co-operative task
for j = 0 to n_workers-1
me.workers(j).Start
next
’ now loop while monitoring progress
Do
globalModule.saveDebugInfo("sleeping co-operative task for 1sec")
thread.SleepCurrent(1000)
globalModule.saveDebugInfo("returned") ' never returns here
...
Execution never returns after thread.SleepCurrent. If me.workers(j).Start is commented out, it works as expected. Debugging from the IDE (that always uses co-operative threads as i understand) also hangs at the first return from worker Run events. Note the above Do Loop executes inside a co-operative task; i have a similar Do Loop in the main thread that in turn monitors this task, and it also hangs.
So there is something seriously wrong with the sleep mechanism with pre-emptive threads running.
BTW, not fully tested but seems that DelayMBS works as expected. I spent hours trying to figure out why my threads were deadlocking. Very frustrating to eventually realize it’s not my doing.
no because the latest in turn has another bug related to incorrect rendering of textfields (I posted recently on this as well).
Beatrix is correct. You need to produce a sample showing the supposed problem and expressing the expected results and what you observe instead, so they can experience the exact same thing as you and find what is going on.
A sample is not necessary when your case can be expressed in few lines one can copy/paste and run. Not your case.
I can’t help but feel that i’m doing xojo’s work for them, but in the interest of moving this along so others don’t get bitten by this, I uploaded a sample project. See the notes. Interestingly, the deadlock only occurs if the main thread is slept periodically, along with the controller task (a co-operative thread) as the PE worker progress is polled. If main does not sleep, but progress is instead monitored with a timer, all seems fine. Maybe this is the way to go.
One thing I notice immediately is that you are using some rather obscure (and brand new) MBS functions, such as AtomicFlagMBS, AtomicIntegerMBS etc.
Per @Christian_Schmitz I would be interested in seeing if this is a Xojo issue, a MBS issue, or perhaps a Xojo + MBS + preemptive thread issue?
With the release of MBS Xojo Plugins version 25.2, developers gain access to a powerful new class designed to help manage concurrency in a thread-safe, lock-free manner: the AtomicFlagMBS class. This lightweight atomic boolean type can be the foundation for building your own synchronization primitives like semaphores or critical sections — without relying on heavyweight system locks.
That thought crossed my mind.I refactored the test project to use regular properties protected by CS’s and there is no difference: Christian’s Atomic objects do not cause the issue.
Coming from somebody that worked for Xojo, there are two primary reasons why you should always include a case:
Volume. Xojo receives lots of cases. If you reduce their workload as much as possible, you greatly increase the chances of the bug being investigated. It’s human nature to go after the low hanging fruit.
Testability. They run your project, see the issue, fix the issue, and use that project again to confirm the fix. Asking them to write the project for you significantly increases the possibility that your description was misunderstood, leading to either an inability to reproduce the issue or the wrong change being made.
The way I see it, either make a sample project, or don’t open the case.
I would add that doing this is like providing a unit test for your case. Something that we all should create for critical functions, but rarely do because it takes extra time. The example projects you provide are great for Xojo to refer back to, to make sure something didn’t get broken along the way when other things are changed.
No. You are doing the work of advocating for your own needs.
As a neuroscientist, you are likely familiar with the notion of behaviors that are emergent from complex systems. They are difficult or impossible to predict from the starting state and rules of the system due to the interactions between all the elements, once the number of elements reaches a certain critical mass.
The same is true of development systems. Very simple development systems exist and can be definitively characterized so that all input states can be mapped to defined output states. However, this quickly becomes impractical as features are added: the problem space expands so rapidly that no mapping is possible.
The result is that development systems become a partnership between the system provider (Xojo) and its users. Xojo creates the product and has an internal testing framework to validate new features as best they can before release - but for the reasons noted above, this can never cover all possible use cases. Developers then have an opportunity to provide feedback about their specific situation and Xojo can take what action they deem necessary to address any issues raised. Ideally, the result is a product that closely matches the needs of its users.
Note that I didn’t say Xojo fixes all issues. They don’t, because not all issues are fixable, and not all issues should be fixed (plenty of issues affect a vanishingly small number of users, for example). Workarounds abound. But on average, I’d say they do a good job.
Done. v2 has app.use_atomic switch (I think i wrapped all references to relevant shared properties, but can’t guarantee). And i fixed the title, i’d copied it from your original case and forgot to update the xojo vers num.
I can also confirm that DelayMBS (it’s in the test project, just commented out) works as expected and does not produce deadlocks.
I modified your V2 to create a V3 version which demonstrates the bug w/o needing MBS plugins.
I think we are seeing the same thing here - the main Thread will sleep for 1000msec normally, as long as other preemptive threads are running, but in the very last loop, after the other threads finish up, the main thread never wakes up from the 1000msec sleep it was in. As a result, the app hangs.