Thread.SleepCurrent() broken in 2025R2.1 with Preemptive thread

Feedback Case Number:77691

Undoubtedly related to https://tracker.xojo.com/xojoinc/xojo/-/issues/77691 which was marked closed and presumably fixed, but isn’t, here is my code snippet:

’ 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.

xojo 2025R2.1 on macOS Sonoma 14.5

Did you try in the latest version of Xojo?

Please open a feedback case or else this issue won’t be addressed.

https://tracker.xojo.com/xojoinc/xojo/-/issues/80611

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).

Your new issue doesn’t have any example.

that’s correct. After spending hours on this, i’ll leave it to the xojo engineers. my snippet should be all they need.

The Xojo people always always ask for an example.

1 Like

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.

1 Like

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.

I’m the author of https://tracker.xojo.com/xojoinc/xojo/-/issues/77691 so I have some interest here. Thank you for submitting a project along with https://tracker.xojo.com/xojoinc/xojo/-/issues/80611

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.

2 Likes

Coming from somebody that worked for Xojo, there are two primary reasons why you should always include a case:

  1. 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.

  2. 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.

9 Likes

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.

1 Like

If you upload that new project to the issue, I’d be happy to test it too.

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.

1 Like

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.

2 Likes

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.

1 Like

What happena if you change the threat.type to cooperative before the sleep?

both slept threads were already cooperative in my version. only the workers were PE.

1 Like

Good news: I was able to trigger the bug in a tiny toy project:
https://tracker.xojo.com/xojoinc/xojo/-/issues/80611

The key seems to be having a mix of Cooperative and Preemptive threads, and then calling

Thread.SleepCurrent(delay)

inside a thread.

The workaround is simply to call
me.Sleep(delay)
in the code inside a thread.

4 Likes

Another advantage of a sample, community contributions, this time even before Xojo touching the case.

Well done, peeps.

3 Likes