What else can I "sleep" when sleep () cannot work well with an alarm?

There are many documents that say: "you should avoid sleep with the alarm, since many systems use the alarm to realize sleep." And in fact, I suffer from this problem. So can someone help me with what else I can "sleep" when sleep () cannot work well with an alarm? I already tried the "sleeping" Time :: HiRes module and the select () function. But they did not work either.

+6
source share
6 answers

You can try AnyEvent :

 use AnyEvent; my $cv = AnyEvent->condvar; my $wait_one_and_a_half_seconds = AnyEvent->timer( after => 1.5, cb => sub { $cv->send } ); # now wait till our time has come $cv->recv; 
+1
source

Having seen how you interrupt alarms, and therefore cannot reliably use sleep () or select (), I suggest using Time :: HiRes :: gettimeofday in combination with select ().

Here is the code that I have not tested. He must resist interruption of signals and will sleep for the desired number of seconds, plus up to 0.1 seconds. If you want to write more processor cycles without doing anything efficiently, you can make the resolution much better:

 ... alarm_resistant_sleep(5); # sleep for 5 seconds, no matter what ... use Time::HiRes; sub alarm_resistant_sleep { my $end = Time::HiRes::time() + shift(); for (;;) { my $delta = $end - Time::HiRes::time(); last if $delta <= 0; select(undef, undef, undef, $delta); } } 
+4
source

Sleep mode can be done using system :

 system ( "sleep", 5 ); 

Or did I misunderstand the question?

+1
source

When using (from the MySQL forum )

 use Sys::SigAction qw( set_sig_handler ); eval { my $hsig = set_sig_handler( 'ALRM', sub { my $canceled = 1; die; }, { mask=>[ qw( INT ALRM ) ] ,safe => 0 } ); alarm($timeout); ... alarm(0); } 

I noticed that any subsequent calls made to sleep($delay) with $timeout shorter than $delay end with the completion of the script and printing " Alarm clock ".

The workaround I found was to call alarm() again, but with an incredibly high value (3600), and immediately cancel this signal.

 eval { alarm(3600); print " .... Meeeep ...."; # Some trace alarm(0); }; 

Then I can use sleep() without any interference.

Example below (real-time code snippet):

 sub unmesswithsleep { eval { alarm(3600); &tracing (8, " .... Meeeep ...."); alarm(0); }; } sub lockDBTables { return (0) unless ($isdbMySQLconnect); my $stm = qq { LOCK TABLES myBIGtable WRITE }; my $timeout = 60; # This is the timer set to protect against deadlocks. Bail out then. eval { my $h = set_sig_handler( 'ALRM', sub { my $canceled = 1; die; }, { mask=>[ qw( INT ALRM ) ] ,safe => 0 } ); alarm($timeout); my $res = $dbmyh->do($stm) + 0; alarm(0); # Reset alarm }; if ( $@ =~ m/Die/i ) { $isdbTabledlocked = 0; &tracerr (0, "FATAL: Lock on Tables has NOT been acquired within ${timeout}s. Lock is set to <$isdbTabledlocked>."); &unmesswithsleep(); # MUST be called each time alarm() is used return (0); } else { $isdbTabledlocked = 1; &tracing (2, " Good: Lock on Tables has been acquired in time. Lock is set to <$isdbTabledlocked>."); &unmesswithsleep(); # MUST be called each time alarm() is used return (1); } # Can use sleep() now. } 
+1
source

try

 print "Start\n"; select undef, undef, undef, 1; print "End\n"; 

It will sleep for 1 second.

0
source

It looks like your hibernation code is interrupted by some code that sets the alarm. This is by design, so you see the expected behavior. In other words, the alarm * should always interrupt the sleep call.

If you are looking for a clean perl sleep path without interrupting an alarm, you can do this by installing your own alarm handler. Thus, when your code receives an alarm, it does not interrupt your processing.

However, it is important to beware that this delays any alarm set by another code. Another code will receive an alert late; after code completion. This means that if you want to play well with others, you are better off using one of the other solutions.

Here is an example:

 #!/usr/bin/perl use POSIX; use strict; use warnings; # set an alarm print "Setting alarm\n"; alarm 1; my $old_alarm; my $snoozed; { # store the previous alarm handler (if any) $old_alarm = $SIG{ALRM}; # override the alarm handler so that we don't # get interrupted local $SIG{ALRM} = sub { print "got alarm; snoozing\n"; # record the fact that we caught an alarm so that # we can propagate it when we're done $snoozed++; }; # sleep for a while. for (1 .. 3) { print "z" x $_ ,"\n"; sleep 1; } } # replace the old sleep handler; $SIG{ALRM} = $old_alarm if $old_alarm; # if we had to snooze fire an immediate alarm; if ($snoozed) { POSIX::raise(POSIX::SIGALRM); } 

The documentation referenced by the prompts but does not describe another symptom. The main thing that you need to worry about when a dream is realized using an alarm is alarm reset when someone causes a dream.

* Apparently, there are several versions of perl (for example: old Win32) where the alarm does not interrupt sleep.

0
source

Source: https://habr.com/ru/post/893753/


All Articles