Recent

Author Topic: Suspending Thread from other Thread under *nix properly  (Read 1238 times)

Skotty

  • New Member
  • *
  • Posts: 13
Suspending Thread from other Thread under *nix properly
« on: March 31, 2020, 12:54:07 am »
Today I ran into a problem with an application I originally programmed under Windows:

A thread should be suspended by another thread. The Unix implementation (tthread.inc) of FPC throws me an error here:
Quote
Suspending one thread from inside another one is unsupported (because it is unsafe and deadlock prone) by *nix and posix operating systems

The comment of the person who wrote this implementation for FPC says:
Quote
Posix doesn't define anything for suspending threads as this is
inherintly unsafe. Just don't suspend threads at points they cannot
control. Therefore, I didn't implement .Suspend() if its called from
outside the threads execution flow (except on Linux _without_ NPTL).

My question is now: How do I properly tell one thread to wait, until another thread tells it to resume?

Usually the answer I found, and would use myself, are RTLEvents.

Edit:
I found the actual solution myself after some more testing
I created a "Pause" method on my thread to set a boolean flag via InterlockedExchange to switch it by any outside thread. Then in my thread's main loop I check if this flag is set. If yes, I use RTLWaitFor. Then I created a "Continue" method which sets the RTLEvent for this, to resume (and of course sets the flag to false).
« Last Edit: March 31, 2020, 01:23:07 am by Skotty »

eljo

  • Sr. Member
  • ****
  • Posts: 468
Re: Suspending Thread from other Thread under *nix properly
« Reply #1 on: March 31, 2020, 01:32:59 am »
As far as I understand threading
1) threadFunc is called from inside the threads execution context to set up things so calling suspend from it is calling it from inside the thread.
2) since suspend calls RtlEventWaitFor(FSuspendEvent) if it is called from an external thread the external thread will get suspended not the thread you wish to suspend.

to accomplish what you are after you need to create your own threads and add a pause method or something along those lines.

This will set/reset an internal rtlevent and set a FPause variable to true. Inside your threads execute procedure you need to check the fpause value regualarly and if it is set then call RtlEventWaitFor(FPause).

You can extend the logic with an extra event that will inform the external thread you are paused and waiting to be unpaused if the external thread needs to make sure that its paused before continuing.

 

TinyPortal © 2005-2018