NO

Author Topic: How to interrupt thrd_sleep?  (Read 4355 times)

Offline Werner

  • Member
  • *
  • Posts: 20
How to interrupt thrd_sleep?
« on: November 29, 2020, 05:25:24 PM »
The C standard reads in

7.26.5.7 The thrd_sleep function (p. 2):

"The thrd_sleep function suspends execution of the calling thread until ... or a signal which is not being ignored is received. If interrupted by a signal ..."

How can I achieve this?

Offline John Z

  • Member
  • *
  • Posts: 790
Re: How to interrupt thrd_sleep?
« Reply #1 on: December 03, 2020, 01:33:59 PM »
Hi,

I think you need to be a bit more specific, or detailed, in your question.

The function is in <threads.h> and of the form
int thrd_sleep(const struct timespec *duration, struct timespec *remaining);

The help file in Pelles C has information.

John Z

Offline John Z

  • Member
  • *
  • Posts: 790
Re: How to interrupt thrd_sleep?
« Reply #2 on: December 04, 2020, 11:16:54 AM »
Hi Werner,

If you were asking how to terminate a sleep before it ends you'll want to look at signal.

The C library function void (*signal(int sig, void (*func)(int)))(int) sets a function to handle signal i.e. a signal handler with signal number sig.

Here is some example code: https://www.tutorialspoint.com/c_standard_library/c_function_signal.htm

If this is not what you were looking for please explain more clearly.

Regards,
John Z

Offline Werner

  • Member
  • *
  • Posts: 20
Re: How to interrupt thrd_sleep?
« Reply #3 on: December 08, 2020, 05:29:06 PM »
I apologize! I thought it were obvious that I intend to terminate the sleep.

Thanks for trying to help me, but I still don't get it.

Before asking, I unsuccessfully tried the attached code which does NOT terminate the sleep. Where am I wrong?

Tia.

Werner


Offline John Z

  • Member
  • *
  • Posts: 790
Re: How to interrupt thrd_sleep?
« Reply #4 on: December 08, 2020, 06:53:12 PM »
Hi Werner,

I copied the example code at the link I posted and just change sleep(1) to _sleep(1).
Complied as a console and ran it.  It worked quite well.  When I hit CTRL+C it sends a 'signal' SIGINT to the sleep procedure and it terminates. 

The key to interrupting sleep is to establish a response to any signal using signal(SIGINT, sighandler);  The first parameter can be any valid signal that you want to raise.  The link show the signals that can be responded to. 

I tested your code sample and it works if you replace thrd_sleep with _sleep(SECS)

I'll take a further look at your code to see if anything is obvious with thrd_sleep (I've not used that before) , but
since it terminated immediately I'd look at how the timer is being set first.

Meanwhile you might try the link I posted to see if that works for you.

John Z

Offline John Z

  • Member
  • *
  • Posts: 790
Re: How to interrupt thrd_sleep?
« Reply #5 on: December 09, 2020, 11:33:20 AM »
Hi Werner,

Well thought I had it working but......not so.
It all works as expected with _sleep(SECS) but not with thrd_sleep  :(
Seems to be an issue with thrd_sleep I think I'll try another compiler just to be sure...
John Z
« Last Edit: December 09, 2020, 11:42:47 PM by John Z »

Offline John Z

  • Member
  • *
  • Posts: 790
Re: How to interrupt thrd_sleep?
« Reply #6 on: December 11, 2020, 02:13:42 PM »
Hi Werner,

Well my conclusion, after quite a lot of testing, is that the thrd_sleep function in the multithread lib and multithread dll has an issue.  Every test points to the fact that it never actually performs any delay. It always returns immediately.  Replacing thrd_sleep with _sleep shows that the program works correctly, and using signal to terminate the sleep early works as well.   

For now, I believe it is a bug....

John Z

Offline Werner

  • Member
  • *
  • Posts: 20
Re: How to interrupt thrd_sleep?
« Reply #7 on: December 12, 2020, 11:28:06 AM »
Thanks again for trying to help!

I have attached an improved version of my program which I have abundantly enriched with comments.

I am waiting eagerly for a solution--if any exists ...

Werner

Offline John Z

  • Member
  • *
  • Posts: 790
Re: How to interrupt thrd_sleep?
« Reply #8 on: December 12, 2020, 02:34:32 PM »
Hi Werner,

I've run your new version and added some timing measurements and broke out the signal handler from a New_thread (which may not be relevant but makes it more clear for me).  Also did not use thrd_sleep in MAIN used _sleep() to keep the signal handler only used by the thread.  This was after I ran your initial program first  :) trying to locate the problem. Great job with the new program clarity and comments.
 
BTW I'm testing on PellesC version 9.00.9 - you?

My testing still shows that thrd_sleep really is the issue as it never actually sleeps.  It just returns immediately.  I'm showing this by using the system ticks. In the output below you'll see that using _sleep(5) uses 11532934082 Ticks while thrd_sleep for 5 sec uses just 1802721, and it should use close to 11532934082.   :(  in New_Thread thrd_sleep for 15 sec used just 360648 ticks so almost nothing......


here is the output:
New_Thread started.
        Initiate sig handler for New_Thread
        Signal handler for New_Thread install succeeded.
        New_Thread thrd_sleep Start at 29820373546754
Main thrd_sleep Start ticks 29820372577372
Main thrd_sleep 5 sec, total ticks were 1802721
Main _sleep() Start ticks were 29820374879708
        New_Thread 15 sec thrd_sleep total ticks were 360648
Main _sleep() 5 sec, total ticks were 11532934082
Going to raise signal to stop thread
termination request -- terminating
*** Process returned 1 ***
Press any key to continue...

---------------------------------------
Anyway it is going to be difficult to show 'Signal' working with thrd_sleep when thrd_sleep is not actually sleeping...… I'm at a loss.  My other compiler does not support multithreading.

Not giving up but will need some new thinking …

John Z

Offline John Z

  • Member
  • *
  • Posts: 790
Re: How to interrupt thrd_sleep?
« Reply #9 on: December 13, 2020, 06:15:24 PM »
Hi Werner,

For you to achieve your objective you will need to use times less than .1sec for both your MAIN_SECS delay and your THRD_SECS delay.  Seems, as implemented, thrd_sleep only accepts times of =<100 million nanoseconds.  This why it always completes before SIGNAL can even act upon it.
 
Not sure if this is a bug or not I've posted in the bug report to see if it is.  Many examples on the web show using times > .1sec like 15 sec,  so could be a bug.   There is a function called _nanosleep which I tried as well, its help file clearly states <100 million nanoseconds limit while thrd_sleep doesn't.


John Z


Well darn - it is a bug on my laptop.... the timing issue I have been experiencing is due to version 9 of the compiler.  In the change log for version 10 is this "and the thrd_sleep function is perhaps less buggy" - I've now put version 10 on the laptop.
« Last Edit: December 14, 2020, 11:27:19 AM by John Z »

Offline John Z

  • Member
  • *
  • Posts: 790
Re: How to interrupt thrd_sleep?
« Reply #10 on: December 14, 2020, 03:13:07 PM »
Hi Werner,

OK now that I have PellesC version 10 running I can help in your quest. I hope  :)

So first there is the matter of interpreting the instructions.
The C standard states in 7.26.5.7 p. 2:
"The thrd_sleep function suspends execution of the calling thread until a signal which is not being ignored is received."

This is true, but what it does not do is terminate the thrd_sleep() function or the _sleep() function.  Using a signal the thrd_sleep can be paused, other work done, but then it is resumed. I'm fairly sure this is/was not your expectation.

To actually terminate the different sleeps you can break up the sleep into loops of the smallest interval you are willing to have.  Note that no sleep guarantees the  exact sleep interval even without looping.

I've modified your code to show this.  The modified code lets you choose to use thrd_sleep, or _sleep(), choose to use a loop method or just straight sleep method.  The screen output is much more detailed to show timing results.    If you run it as posted (loop method) you will see an escape from the thrd_sleep set for 15 sec, with main sleep at 5 before signaling, results in showing 10 sec remaining.  Then change to not using a loop to see the output.

In the signal handler I just set a kill flag but other procedures could be called too.  PellesC doesn't currently support thrd_kill() which could simplify it too.

To change operation change the defines at the start of the program and recompile.
Here it the output:
----Entered destructor with 1----

Time 07:51:18 -         Initiate sig handler for New_Thread, ticks 34143895461518
Time 07:51:18 - In Main back from thrd create 5 sec, total ticks were 0
Time 07:51:18 -         Signal handler for New_Thread install succeeded, ticks 34143895461518
Time 07:51:18 - Main thrd_sleep Start ticks 34143904744397
Time 07:51:18 -         New_Thread thrd_sleep Start at 34143905066208 for 15
Time 07:51:23 - Main thrd_sleep End 5 sec, total ticks were 11532863889
Time 07:51:23 - Main thrd_sleep residual 0 sec
Time 07:51:23 - Going to raise signal to stop thread, ticks 34143904744397
Time 07:51:23 -                  Interrupt signal received 34155444130170 ticks.
                                 raised SIGINT
Time 07:51:23 - sig_handler alerted at 34155446511792 ticks.
Time 07:51:23 - Signal handler finished its job, ticks 34143904744397
Time 07:51:23 -         New_Thread 15 sec thrd_sleep total ticks were 11604411594
Time 07:51:23 -         New_Thread terminate with 10 sec remaining 10
                Start 3078, End 3083. Remaining 10
Time 07:51:23 -         New_Thread terminating, ticks 34143905066208
Time 07:51:23 - New thread successfully joined, ticks 34143904744397
Sleeping time of "thrd_sleep" in "New_Thread":
Interuption:
Remaining secs  = 10
Remaining nsecs = 0
Press any key to continue...
---------------------------------

Hope this helps,

John Z

Offline Werner

  • Member
  • *
  • Posts: 20
How to interrupt thrd_sleep? *** SOLVED ***
« Reply #11 on: December 14, 2020, 08:46:20 PM »
John:

Thank you very much for your contributions!

In the meantime I succeeded in solving my problems.
I have attached 2 programs which were compiled using Pelles C Version 10.00.6.

Thanks again for your support.

Werner

Offline John Z

  • Member
  • *
  • Posts: 790
You got it . . .
« Reply #12 on: December 14, 2020, 11:36:18 PM »
Thanks for sharing Werner, glad you achieved your objective.  That always feels good.

Cheers,

John Z

Offline Werner

  • Member
  • *
  • Posts: 20
Re: How to interrupt thrd_sleep? *** CORRECTED SOLUTION ***
« Reply #13 on: December 15, 2020, 06:06:05 AM »
I realized only now that I published the programs with identical names.

So I am publishing renamed versions:

1) thrd_sleep_test
It only checks the correct function of thrd_sleep.

2) thrd_sleep_handler
It shows how to interupt a running thrd_sleep.

I am adding a helper program:

3) timespec_mt
It shows how to correctly initialize a struct timespec, which is needed by thrd_sleep.

Sorry for the inconvenience.

Werner

Offline John Z

  • Member
  • *
  • Posts: 790
Re: How to interrupt thrd_sleep?
« Reply #14 on: December 15, 2020, 12:24:35 PM »
Hi Werner,

No problem , I renamed _a and _b when downloading  :) but I'll get these new one too.

I'd like to point out, perhaps to clarify an item or two, my opinions of course.

IMO the use of thrd_sleep() or _sleep() could occur in a program possibly in various, and multiple, places within a program that might need to be slowed, or delayed for something slower.  For example an animation.  I used something similar to slow the animation down to be more visually pleasing rather than one jump.  I would not put thrd_sleep() in the signal procedure in a real application.  The signal procedure normally is used to service the interrupt. Its not wrong of course and it works as you demonstrate.

Regarding thrd_sleep() itself, here is the section of ISO-9899 describing thrd_sleep().

Quote
7.26.5.7 [The thrd_sleep function]

 1           #include <threads.h>
            int thrd_sleep(const struct timespec *duration,
                 struct timespec *remaining);
    Description

 2   The thrd_sleep function suspends execution of the calling thread until either the
    interval specified by duration has elapsed or a signal which is not being ignored is
    received. If interrupted by a signal and the remaining argument is not null, the
    amount of time remaining (the requested interval minus the time actually slept) is stored
    in the interval it points to. The duration and remaining arguments may point to the
    same object.

I'm trying to convince you :) that interrupted does not mean terminated, and if we assume that that is true then thrd_sleep() is working as intended when it resumes sleeping until the interval has been achieved, after the interrupt has been serviced.  In the words of the great detective MONK - I could be wrong but I don't think so.... I think they would have used the wording  "terminated by a signal" rather than "interrupted by a signal".

This is a great investigation with testing, it will benefit others by having working example(s) of these features of C. 

John Z