polettix has asked for the wisdom of the Perl Monks concerning the following question:

Wise Monks,

this is more a request for confirmation than a real question, because it seems that I worked out by myself.

I have to use a Java application to do some homework stuff about neural networks (using Joone), but I mostly hate to use Java and so I reduced its usage to a minimum. I resorted to use a controlling Perl script, which spawns the different Java applications and reads results from their standard output.

This time, too, the operations are quite lengthy, and I only have a personal laptop for these computations. In the evening I like to go home, but stopping a 2-hour computation and waste it is not good (some of you may recall I'm not new to this kind of problems: Variable persistence for suspend-and-resume programs). So, I implemented a save-and-resume mechanism inside the Java code, based on the test for presence of a file inside the filesystem as a signal from the outside to stop computing, save all and exit. Yes, I don't even want to know how Java handles real signaling.

In the Perl script, I set $SIG{INT} to generate the given file as follows:

$SIG{INT} = sub { open my $fh, ">PleaseStop" or warn "open(PleaseStop): $!"; }
At the very start of the program I also wipe out the PleaseStop file, of course. Then, later in the program, I called the Java app like this:
my $outcome = qx/java MyClass param1 param2 param3 ... /;
As you may guess, this approach fails half of the time to give the required graceous-stop behaviour. After some time, I realised that the backtick/qx operator actually calls fork() at some time, and I probably end up with two possible situations: in the desired one the Perl script is receiving the INT when I hit CTRL-C; in the other, it's the Java program that receives the signal.

As anticipated, I have no will to dig the secrets of signal handling in Java, so I worked out the following solution: disabling the INT signal before the call to the Java program, but not in the main Perl script:

# When it's time to call... call call_command sub call_command { my $command = shift; my ($pid, $rd, $wt); { local $SIG{INT} = 'IGNORE'; $pid = open2($rd, $wt, $command); # From IPC::Open2 } my $outcome = join "", <$rd>; waitpid $pid, 0; return $outcome; }
Yes, I know that the call to waitpid should be more robust, but this is not a widespread script and I can live with it.

Is this approach correct, or should I do something better? Do you see troubles in my future with this? I work with Perl 5.8.6 in Linux (kernel 2.4), and I don't plan to use the script other than in this environment.

Flavio
perl -ple'$_=reverse' <<<ti.xittelop@oivalf

Don't fool yourself.

Replies are listed 'Best First'.
Re: Signal handling with (implicit) fork
by idsfa (Vicar) on Aug 02, 2005 at 19:17 UTC

    Of course this isn't the correct approach. You've indicated several times that you know what the correct approach is. Fixing your suspend problems would probably be even better.

    You are likely to have problems if a non-masked thread in your JVM receives the SIGINT instead. This can happen if you are using a shared JVM between processes. If you completely control the environment, this is avoidable.

    This is a kludge. It works, but it's a kludge.

    Now if you want to avoid Java altogether, you should look at CPAN.

    Updated (OT): Here's the Java code you would need to have your apps handle a Ctrl-C gracefully:

    class ExampleShutdownHook { public static void main(String[] args) { // Java code to install shutdown hook: MyShutdown MyShutdown sh = new MyShutdown(); Runtime.getRuntime().addShutdownHook(sh); // Do the Joone stuff // . // . // . } } // Example shutdown hook class class MyShutdown extends Thread { public void run() { System.out.println("MyShutdown hook called"); // Dump the shutdown file // . // . // . } }

    The intelligent reader will judge for himself. Without examining the facts fully and fairly, there is no way of knowing whether vox populi is really vox dei, or merely vox asinorum. -- Cyrus H. Gordon
      This is the kind of hand-slapping I was actually looking for - I somehow sensed that it was a bad application of Laziness. But there still remain some meat IMHO: if I were to call a "simpler" program, would this be the correct way to pre-mask a signal from Perl, or do exist more robust methods?

      Thank you for the precious pointers and the OT effort :)

      Flavio
      perl -ple'$_=reverse' <<<ti.xittelop@oivalf

      Don't fool yourself.
Re: Signal handling with (implicit) fork
by perlfan (Parson) on Aug 02, 2005 at 16:35 UTC
    If you are using a Perl script to spawn these processes, why can't you just suspend the Perl script (or the jvm for that matter) with ctrl-z or nice it down?
      I have to shut the laptop down and I've no support for a system-suspend at the moment, unluckly.

      Flavio
      perl -ple'$_=reverse' <<<ti.xittelop@oivalf

      Don't fool yourself.