It looks like the problem exists at the C level as well.  This code doesn't
work past the first alarm:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <time.h>

int n;
char s[10];
char* prog;

int alarm_called = 0;

void handle_alrm(int signo) {
if (signo == SIGALRM) {
execv(prog, (char*[]) { prog, s, NULL });
}
}


int main(int argc, char** argv) {
prog = argv[0];

if (argc == 1) {
n = 1;
} else {
n = atoi((const char*)argv[1]);
}

printf("run %d\n", n);
n++;

snprintf(s, 10, "%d", n);

signal(SIGALRM, handle_alrm);

alarm(1);
sleep(3);
alarm(0);

return 0;
}

But this code does work:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <time.h>

int n;
char s[10];
char* prog;

int alarm_called = 0;

void handle_alrm(int signo) {
if (signo == SIGALRM) {
alarm_called = 1;
}
}


int main(int argc, char** argv) {
prog = argv[0];

if (argc == 1) {
n = 1;
} else {
n = atoi((const char*)argv[1]);
}

printf("run %d\n", n);
n++;

snprintf(s, 10, "%d", n);

signal(SIGALRM, handle_alrm);

alarm(1);
sleep(3);
if (alarm_called) {
execv(prog, (char*[]) { prog, s, NULL });
}
alarm(0);

return 0;
}


On Tue, Oct 4, 2016 at 10:40 AM Chas. Owens <chas.ow...@gmail.com> wrote:

> First, never use -w flag to enable warnings; use the warnings pragma
> instead.
>
> Second, you should not exec the script directly, you don't know if it is
> executable or not, and it could even wind up running under a different
> version of perl.  Instead, you should exec same the interpreter that is
> running the current program.  Happily perl stores the path to the current
> interpreter in $^X for you.
>
> It appears as if the process becomes insensitive to the SIG_ALRM signal if
> you run exec within the signal handler.  In general you should avoid doing
> anything in a signal handler other than setting a status variable.  This
> code seems to work the way you were expecting:
>
> #!/usr/bin/perl
> use strict;
> use warnings;
>
> my $n = shift || 1;
>
> my $exec = 0;
>
> $SIG{ALRM} = sub { die "timeout\n" };
>
> print "\$\$ is $$ this is run $n\n";
>
> alarm 1;
> eval {
> sleep 5;
> alarm 0;
> 1;
> } or do {
> alarm 0; # handle cases where it wasn't a timeout that died
> if ($@ eq "timeout\n") {
> exec $^X, $0, $n + 1;
> }
> };
>
> print "should not get here\n";
>
> What are you trying to solve with this code?  Is this just academic
> playing around?  If not, there may be a much better solution than
> re-execing the script.
>
>
> On Tue, Oct 4, 2016 at 12:13 AM Unknown User <knowsuperunkn...@gmail.com>
> wrote:
>
> I am trying to re-exec my script after a delay. I expect that the code
> below would go on re-execing indefinitely, however that does not
> happen. It exits after one reexec. What should be done to make the
> code re-exec forever?
>
> $ cat exec.pl
> #!/usr/bin/perl -w
> use strict;
> alarm(5);
> $SIG{"ALRM"} = sub {
> print "Reexecing\n";
> exec($0,@ARGV);
> };
>
> print join(".",@ARGV);
> sleep 12;
> $ ./exec.pl 1 2 3 4
> 1.2.3.4Reexecing
> 1.2.3.4$
> $
>
> --
> To unsubscribe, e-mail: beginners-unsubscr...@perl.org
> For additional commands, e-mail: beginners-h...@perl.org
> http://learn.perl.org/
>
>
>

Reply via email to