Recent

Author Topic: Sleep forever  (Read 3663 times)

jollytall

  • Sr. Member
  • ****
  • Posts: 320
Re: Sleep forever
« Reply #15 on: November 29, 2023, 03:56:12 pm »
Thaddy, can I access the "suspended" property for the main program as well? Is there such a property in a console (actually not even a console, but a daemon) application?

Mr.MadGuy, I also use the TCriticaSection a lot (as shown earlier), but in order to use it as a tool to stop my main thread, I need one of the sub-threads to EnterCriticalSection. As my sub-threads are not made to stop the main program, the trick would be to make yet another thread the Enters the Critical Section that stops the main thread, what cannot Enter while it is blocked. It is a bit overkill to make one more thread just to stop the main program but it works:
Code: Pascal  [Select][+][-]
  1. var
  2.   CS : tRtlCriticalSection;
  3.  
  4. function MyThread({%H-}aParam : pointer) : {$IFDEF CPUARM} LongInt {$ELSE} Int64 {$ENDIF};
  5.   begin
  6.   writeln('Thread launched');   // This should happen earlier then the main program trying to Enter
  7.   InitCriticalSection(CS);
  8.   EnterCriticalSection(CS);
  9.   writeln('Thread finishes');
  10.   EndThread;
  11.   result := 0;
  12.   end;
  13.  
  14. begin
  15. writeln('Will start thread');   // First step
  16. BeginThread(@MyThread);         // Launch the thread
  17. writeln('Thread started');      // It actually happens earlier than the "Thread launched" message from the thread
  18. Sleep(1000);                    // Need to wait a bit, to make sure the thread is started
  19. writeln('Will try to Enter');   // This must happen after the thread already blocked the Critical Section
  20. EnterCriticalSection(CS);       // It is blocked here
  21. writeln('Main program ran on'); // <--- Never happens
  22. end.
Now my only question, if it is actually less clock cycle intense than just do an infinite loop with e.g. Sleep(10000)?

440bx

  • Hero Member
  • *****
  • Posts: 4224
Re: Sleep forever
« Reply #16 on: November 30, 2023, 01:12:57 am »
Now my only question, if it is actually less clock cycle intense than just do an infinite loop with e.g. Sleep(10000)?
I cannot answer the question conclusively because it depends on how EnterCriticalSection is implemented but, the infinite loop with a large Sleep() should use fewer clock cycles because a Sleep informs the scheduler _not_ to provide clock cycles to the thread whereas a call to EnterCriticalSection usually enters a loop that continuously tries to enter the critical section and, depending on how that is implemented, that can potentially consume a noticeable amount of CPU.

If I were you, I'd use the infinite Sleep loop. Once the sleep state is entered, which always occurs "immediately", i.e, no need to "retry", that thread gets no clock cycles which is the goal.

HTH.
(FPC v3.0.4 and Lazarus 1.8.2) or (FPC v3.2.2 and Lazarus v3.2) on Windows 7 SP1 64bit.

Warfley

  • Hero Member
  • *****
  • Posts: 1511
Re: Sleep forever
« Reply #17 on: November 30, 2023, 07:13:36 am »
As a word of warning, I found myself in a position where I could benefit from signal handling to forcibly abort a background thread, but as the code began to get more complex it turned out to be more trouble than it was worth:

Just as a word of caution, because people tend to use signals carelessly, the POSIX standard puts major restrictions on the use of signals: https://pubs.opengroup.org/onlinepubs/9699919799/functions/signal.html
Quote
the behavior is undefined if the signal handler refers to any object [CX] [Option Start]  other than errno [Option End]  with static storage duration other than by assigning a value to an object declared as volatile sig_atomic_t, or if the signal handler calls any function defined in this standard other than [CX] [Option Start]  one of the functions listed in Signal Concepts. [Option End]

So pretty much anything other than setting a single boolean flag is not allowed (you are not even allowed to read that boolean flag beforehand).

PS: I don't know if pascal even has an equivalent to volatile, or guaranteed atomic types like sig_atomic_t

MarkMLl

  • Hero Member
  • *****
  • Posts: 6936
Re: Sleep forever
« Reply #18 on: November 30, 2023, 08:22:52 am »
Just as a word of caution, because people tend to use signals carelessly, the POSIX standard puts major restrictions on the use of signals: https://pubs.opengroup.org/onlinepubs/9699919799/functions/signal.html

Yes, but in my case the problems were caused by "odd" behaviour when attempting to use HUP for two different things: tell a thread to break any loops etc. and have the main program reread its configuration. It was something to do with the rules regarding which signals could be permanently disabled, in the end I worked around the issue some other way.

MarkMLl

p.s. "volatile" is a Cism. I'm sure that some would argue that Pascal, as a more mature language, doesn't need such things.
MT+86 & Turbo Pascal v1 on CCP/M-86, multitasking with LAN & graphics in 128Kb.
Pet hate: people who boast about the size and sophistication of their computer.
GitHub repositories: https://github.com/MarkMLl?tab=repositories

440bx

  • Hero Member
  • *****
  • Posts: 4224
Re: Sleep forever
« Reply #19 on: November 30, 2023, 08:38:15 am »
p.s. "volatile" is a Cism. I'm sure that some would argue that Pascal, as a more mature language, doesn't need such things.
It's not really a C-ism.  "volatile" informs the compiler that the value in a variable may be altered externally, that is by code that is not part of the function being compiled, therefore the compiler cannot make any assumptions regarding its stability value-wise, which forces the compiler to reload its value immediately before using it.
(FPC v3.0.4 and Lazarus 1.8.2) or (FPC v3.2.2 and Lazarus v3.2) on Windows 7 SP1 64bit.

jollytall

  • Sr. Member
  • ****
  • Posts: 320
Re: Sleep forever
« Reply #20 on: November 30, 2023, 08:43:17 am »
If I were you, I'd use the infinite Sleep loop. Once the sleep state is entered, which always occurs "immediately", i.e, no need to "retry", that thread gets no clock cycles which is the goal.

I made a small test. Wrote two programs, one with the thread playing trick, using a new Suspend routine
Code: Pascal  [Select][+][-]
  1. function SuspendThread(aParam : pointer) : {$IFDEF CPUARM} LongInt {$ELSE} Int64 {$ENDIF};
  2.   begin
  3.   EnterCriticalSection(tRtlCriticalSection(aParam^));
  4.   result := 0;
  5.   EndThread;
  6.   end;
  7. procedure Suspend;
  8.   var CS : tRtlCriticalSection;
  9.   begin
  10.   InitCriticalSection({%H-}CS);
  11.   BeginThread(@SuspendThread, @CS);
  12.   Sleep(1000);
  13.   EnterCriticalSection(CS);
  14.   end;
  15.  
and the other with a simple loop:
Code: Pascal  [Select][+][-]
  1. while true do
  2.   Sleep(10000);
So far, I only see the loop version eating some - minimal - CPU, while the suspend version uses 0. However this is only my two programs. I can imagine that somewhere else in a linux internal daemon I still use a lot of CPU for the suspend version, what I simply do not see among the many.
« Last Edit: November 30, 2023, 10:55:31 am by jollytall »

cdbc

  • Hero Member
  • *****
  • Posts: 1250
    • http://www.cdbc.dk
Re: Sleep forever
« Reply #21 on: November 30, 2023, 09:30:23 am »
Hi
You can try this event-interface wrapper attached.
how to use:
Code: Pascal  [Select][+][-]
  1. uses sync.event;
  2. var ev: IbcEvent;
  3. begin
  4.   ev:= CreateEventSvc;
  5.   writeln('Waiting...');
  6.   ev.Waitfor; // or
  7. { this way you break every 10 seconds if thats of use to you...
  8.   while true do ev.Waitfor(10000);
  9. }
  10. end;
  11.  
To set the event you call "ev.Signal" from another thread; It resets after done waiting.
edit: added writeln...
Regards Benny
« Last Edit: November 30, 2023, 09:33:33 am by cdbc »
If it ain't broke, don't fix it ;)
PCLinuxOS(rolling release) 64bit -> KDE5 -> FPC 3.2.2 -> Lazarus 2.2.6 up until Jan 2024 from then on it's: KDE5/QT5 -> FPC 3.3.1 -> Lazarus 3.0

MarkMLl

  • Hero Member
  • *****
  • Posts: 6936
Re: Sleep forever
« Reply #22 on: November 30, 2023, 09:32:08 am »
p.s. "volatile" is a Cism. I'm sure that some would argue that Pascal, as a more mature language, doesn't need such things.
It's not really a C-ism.  "volatile" informs the compiler that the value in a variable may be altered externally, that is by code that is not part of the function being compiled, therefore the compiler cannot make any assumptions regarding its stability value-wise, which forces the compiler to reload its value immediately before using it.

My comment was entirely tongue-in-cheek, and was aimed at those members of the community who are inclined to argue that the compiler ignoring e.g. "inline" is venial rather than mortal.

MarkMLl
MT+86 & Turbo Pascal v1 on CCP/M-86, multitasking with LAN & graphics in 128Kb.
Pet hate: people who boast about the size and sophistication of their computer.
GitHub repositories: https://github.com/MarkMLl?tab=repositories

440bx

  • Hero Member
  • *****
  • Posts: 4224
Re: Sleep forever
« Reply #23 on: November 30, 2023, 10:09:37 am »
My comment was entirely tongue-in-cheek,
I missed that in the text ;)
(FPC v3.0.4 and Lazarus 1.8.2) or (FPC v3.2.2 and Lazarus v3.2) on Windows 7 SP1 64bit.

jollytall

  • Sr. Member
  • ****
  • Posts: 320
Re: Sleep forever
« Reply #24 on: November 30, 2023, 11:16:16 am »
@cdbc,
Thanks for the effort. I checked it, but it uses both Critical Section and Events. Then my Suspend seems easier.

PascalDragon

  • Hero Member
  • *****
  • Posts: 5548
  • Compiler Developer
Re: Sleep forever
« Reply #25 on: December 01, 2023, 09:57:47 pm »
The easy way is  to set/get the TThread.Suspended property, which is cross platform.

TThread.Suspended uses TThread.Suspend for which the documentation explicitly states that on non-Windows platforms (or more precisely *nix systems) a thread can only suspend itself, because there simply is no functionality to suspend another thread in pthreads.

jcathey

  • Newbie
  • Posts: 1
Re: Sleep forever
« Reply #26 on: May 29, 2024, 04:08:23 pm »
The canonical (and exceedingly old) way to sleep forever in Unix is (in C):
Code: C  [Select][+][-]
  1. while (1)
  2.    pause();
I do not know if FPC has an fpPause procedure or not.  (It should, IMHO).  This is like the forever sleep mentioned earlier by the OP, but without the waking up he was concerned about.  (It's waiting for incoming signals, only.)  In fact, the original implementation of sleep() in libc looked a lot like this internally, using a SIGALRM to wake up and break the pause() system call.

« Last Edit: May 29, 2024, 07:35:53 pm by jcathey »

marcov

  • Administrator
  • Hero Member
  • *
  • Posts: 11605
  • FPC developer.
Re: Sleep forever
« Reply #27 on: May 29, 2024, 04:19:05 pm »
sysutils.Sleep() is portable.

 

TinyPortal © 2005-2018