in reply to Timeout and kill

You didn't include all of your code so I'm not entirely sure what you are doing.

But, don't use fork() (or threads) if you want things to run sequentially. fork() is why you are seeing multiple processes. You can still use alarm() without it.

Replies are listed 'Best First'.
Re^2: Timeout and kill
by nelson64 (Initiate) on Mar 20, 2012 at 18:22 UTC
    Sorry it's a long script so I was trying to give the portion of code that is the problem. This is the subprocedure:
    sub processCnfDirectory { use Time::HiRes(gettimeofday); use File::Basename; my($path) = @_; my $pid; local $SIG{ALRM} = sub { $didTimeout=1; print OUTPUT "timeout"; print "process id", $pid, "\n"; kill 9, $pid; die "Timeout\n"; }; print( "working in: $path\n" ); # append a trailing / if it's not there $path .= '/' if($path !~ /\/$/); # loop through the files contained in the directory for my $file (glob($path . '*')) { # check if the file is a directory if( -d $file) # pass the directory to the routine ( recursion ) processCnfDirectory($file); } elsif ($file =~ /.*\.cnf/) { print OUTPUT basename($file), ","; # run using the first solver $pid = fork; eval { $didTimeout=0; $start1=gettimeofday(); alarm $timeout; #$pid = `$solver1 $file`; $result = `$solver1 $file`; waitpid($pid, 0); }; alarm 0; $end1=gettimeofday(); if($didTimeout == 0) { print OUTPUT $end1 - $start1; } print OUTPUT ","; # run using the second solver $pid = fork; eval { $didTimeout=0; $start2=gettimeofday(); alarm $timeout; #$pid = `$solver2 $file`; $result = `$solver2 $file`; waitpid($pid, 0); }; }; alarm 0; $end2=gettimeofday(); if($didTimeout == 0) { print OUTPUT $end2 - $start2; } print OUTPUT "\n"; } } }
    So what it does is it reads in a directory on the command line. It loops through the directory recursively to include subdirectories. Inside a directory it runs a solver on each file. Then it records the amount of time it took to run. The solvers are also command line input.

      Okay, you still don't need to use fork(). When you use backticks like that, perl runs that command in another process which you can kill - no fork() needed.

      You may want to look at File::Find instead of glob. It makes this kind of thing easier.

        I don't see what you are doing with $result, but one way is to capture the process ID from the shell:

        $pid = `command && echo $$` ;

        I suggest you take a step back and start again with File::Find. I think you've overcomplicated your solution.

        You might also try to prevent the OOM issue in the "solver" instead.

        I was using fork to obtain the pid. How would I obtain the pid without using fork so I can kill it?