Tim Waugh f80a31
diff -up foomatic-filters-3.0-20080211/foomatic-rip.in.clean-up-on-cancel foomatic-filters-3.0-20080211/foomatic-rip.in
Tim Waugh f80a31
--- foomatic-filters-3.0-20080211/foomatic-rip.in.clean-up-on-cancel	2008-02-11 21:16:36.000000000 +0000
Tim Waugh f80a31
+++ foomatic-filters-3.0-20080211/foomatic-rip.in	2008-03-13 11:42:35.000000000 +0000
Tim Waugh f80a31
@@ -155,19 +155,19 @@ my $EXIT_PRNERR_NORETRY = 2;  # printer 
Tim Waugh f80a31
 my $EXIT_JOBERR = 3;          # job is defective
Tim Waugh f80a31
 my $EXIT_SIGNAL = 4;          # terminated after catching signal
Tim Waugh f80a31
 my $EXIT_ENGAGED = 5;         # printer is otherwise engaged (connection 
Tim Waugh f80a31
-                           # refused)
Tim Waugh f80a31
+                              # refused)
Tim Waugh f80a31
 my $EXIT_STARVED = 6;         # starved for system resources
Tim Waugh f80a31
 my $EXIT_PRNERR_NORETRY_ACCESS_DENIED = 7;     # bad password? bad port
Tim Waugh f80a31
-                                            # permissions?
Tim Waugh f80a31
+                                               # permissions?
Tim Waugh f80a31
 my $EXIT_PRNERR_NOT_RESPONDING = 8;            # just doesn't answer at all 
Tim Waugh f80a31
-                                            # (turned off?)
Tim Waugh f80a31
+                                               # (turned off?)
Tim Waugh f80a31
 my $EXIT_PRNERR_NORETRY_BAD_SETTINGS = 9;      # interface settings are invalid
Tim Waugh f80a31
 my $EXIT_PRNERR_NO_SUCH_ADDRESS = 10;          # address lookup failed, may be 
Tim Waugh f80a31
-                                            # transient
Tim Waugh f80a31
+                                               # transient
Tim Waugh f80a31
 my $EXIT_PRNERR_NORETRY_NO_SUCH_ADDRESS = 11;  # address lookup failed, not 
Tim Waugh f80a31
-                                            # transient
Tim Waugh f80a31
+                                               # transient
Tim Waugh f80a31
 my $EXIT_INCAPABLE = 50;                       # printer wants (lacks) features
Tim Waugh f80a31
-                                            # or resources
Tim Waugh f80a31
+                                               # or resources
Tim Waugh f80a31
 # Standard Unix signal names
Tim Waugh f80a31
 #my SIGHUP = 1;
Tim Waugh f80a31
 #my SIGINT = 2;
Tim Waugh f80a31
@@ -181,6 +181,21 @@ my $EXIT_INCAPABLE = 50;                
Tim Waugh f80a31
 
Tim Waugh f80a31
 my $ESPIPE = 29;	# the errno value when seeking a pipe or socket
Tim Waugh f80a31
 
Tim Waugh f80a31
+# The modern_shell() function will register the PIDs of all shell calls,
Tim Waugh f80a31
+# so that rip_die() can kill these processes 
Tim Waugh f80a31
+my %pids;
Tim Waugh f80a31
+
Tim Waugh f80a31
+# $kidgeneration stays 0 for the main process, child processes of the
Tim Waugh f80a31
+# main process get $kidgeneration = 1, their children 2, ...
Tim Waugh f80a31
+my $kidgeneration = 0;
Tim Waugh f80a31
+
Tim Waugh f80a31
+# Catch signals
Tim Waugh f80a31
+my $retval = $EXIT_PRINTED;
Tim Waugh f80a31
+use sigtrap qw(handler set_exit_canceled normal-signals
Tim Waugh f80a31
+               handler set_exit_error error-signals
Tim Waugh f80a31
+               handler set_exit_prnerr USR1 
Tim Waugh f80a31
+	       handler set_exit_prnerr_noretry USR2
Tim Waugh f80a31
+	       handler set_exit_engaged TTIN);
Tim Waugh f80a31
 
Tim Waugh f80a31
 
Tim Waugh f80a31
 ## Some important variables
Tim Waugh f80a31
@@ -2153,7 +2168,7 @@ if ($debug) {
Tim Waugh f80a31
 }
Tim Waugh f80a31
 
Tim Waugh f80a31
 
Tim Waugh f80a31
-	    
Tim Waugh f80a31
+
Tim Waugh f80a31
 ## From here on we have to repeat all the rest of the program for
Tim Waugh f80a31
 ## every file to print
Tim Waugh f80a31
 
Tim Waugh f80a31
@@ -3538,13 +3553,8 @@ sub getrendererhandle {
Tim Waugh f80a31
 
Tim Waugh f80a31
     print $logh "${added_lf}Starting renderer\n";
Tim Waugh f80a31
 
Tim Waugh f80a31
-    # Catch signals
Tim Waugh f80a31
+    # Reset return value of the renderer
Tim Waugh f80a31
     $retval = $EXIT_PRINTED;
Tim Waugh f80a31
-    use sigtrap qw(handler set_exit_prnerr USR1 
Tim Waugh f80a31
-		   handler set_exit_prnerr_noretry USR2
Tim Waugh f80a31
-		   handler set_exit_engaged TTIN);
Tim Waugh f80a31
-
Tim Waugh f80a31
-    # Variables for the kid processes reporting their state
Tim Waugh f80a31
 
Tim Waugh f80a31
     # Set up a pipe for the kids to pass their exit stat to the main process
Tim Waugh f80a31
     pipe KID_MESSAGE, KID_MESSAGE_IN;
Tim Waugh f80a31
@@ -3585,6 +3595,8 @@ sub getrendererhandle {
Tim Waugh f80a31
         return ( *KID3, $kid3 );
Tim Waugh f80a31
 
Tim Waugh f80a31
     } else {
Tim Waugh f80a31
+	$kidgeneration += 1;
Tim Waugh f80a31
+
Tim Waugh f80a31
         close KID3;
Tim Waugh f80a31
 
Tim Waugh f80a31
         pipe KID4_IN, KID4;
Tim Waugh f80a31
@@ -3774,6 +3786,8 @@ sub getrendererhandle {
Tim Waugh f80a31
 	    print $logh "KID3 finished\n";
Tim Waugh f80a31
 	    exit $EXIT_PRINTED;
Tim Waugh f80a31
         } else {
Tim Waugh f80a31
+	    $kidgeneration += 1;
Tim Waugh f80a31
+
Tim Waugh f80a31
             # child, trailing task on the pipe; we write jcl stuff
Tim Waugh f80a31
             close KID4;
Tim Waugh f80a31
 	    close KID3_IN;
Tim Waugh f80a31
@@ -4112,6 +4126,8 @@ sub getfileconverterhandle {
Tim Waugh f80a31
         return ( *KID1_IN, $kid1 );
Tim Waugh f80a31
 
Tim Waugh f80a31
     } else {
Tim Waugh f80a31
+	$kidgeneration += 1;
Tim Waugh f80a31
+
Tim Waugh f80a31
 	# We go on reading the job data and stuff it into the file
Tim Waugh f80a31
 	# converter
Tim Waugh f80a31
         close KID1_IN;
Tim Waugh f80a31
@@ -4253,6 +4269,8 @@ sub getfileconverterhandle {
Tim Waugh f80a31
 	    print $logh "KID1 finished\n";
Tim Waugh f80a31
 	    exit $EXIT_PRINTED;
Tim Waugh f80a31
         } else {
Tim Waugh f80a31
+	    $kidgeneration += 1;
Tim Waugh f80a31
+
Tim Waugh f80a31
             # child, first part of the pipe, reading in the data from
Tim Waugh f80a31
 	    # standard input and stuffing it into the file converter
Tim Waugh f80a31
 	    # after putting in the already read data (in $alreadyread)
Tim Waugh f80a31
@@ -4580,6 +4598,8 @@ sub getdocgeneratorhandle {
Tim Waugh f80a31
         return ( *KID0_IN, $kid0 );
Tim Waugh f80a31
     }
Tim Waugh f80a31
 
Tim Waugh f80a31
+    $kidgeneration += 1;
Tim Waugh f80a31
+
Tim Waugh f80a31
     # we are the kid; we generate the documentation page
Tim Waugh f80a31
 
Tim Waugh f80a31
     close KID0_IN;
Tim Waugh f80a31
@@ -4867,66 +4887,100 @@ sub rip_die {
Tim Waugh f80a31
     my $errmsg = "$!";
Tim Waugh f80a31
     my $errcod = $! + 0;
Tim Waugh f80a31
 
Tim Waugh f80a31
-    # Close the documentation page generator (if it was used)
Tim Waugh f80a31
-    if ($docgeneratorpid) {
Tim Waugh f80a31
-	if ($kid0) {
Tim Waugh f80a31
-	    print $logh "Killing process $kid0 (KID0)\n";
Tim Waugh f80a31
-	    kill(9, $kid0);
Tim Waugh f80a31
+    # Log that we are dying ...
Tim Waugh f80a31
+    print $logh "Process dying with \"$message\", exit stat: $exitstat\n\terror: $errmsg ($errcod)\n";
Tim Waugh f80a31
+
Tim Waugh f80a31
+    print $logh "Cleaning up ...\n";
Tim Waugh f80a31
+    foreach my $killsignal (15, 9) {
Tim Waugh f80a31
+
Tim Waugh f80a31
+	# Kill all registered subshells
Tim Waugh f80a31
+	foreach my $pid (keys %pids) {
Tim Waugh f80a31
+	    print $logh "Killing process $pid ($pids{$pid}) and its subprocesses with signal $killsignal\n";
Tim Waugh f80a31
+	    # This call kills the process group with group ID $pid, the
Tim Waugh f80a31
+	    # group which was formed from the initial process $pid which
Tim Waugh f80a31
+	    # contains $pid and all its subprocesses
Tim Waugh f80a31
+	    kill(-$killsignal, $pid);
Tim Waugh f80a31
+	    # If the system does not support process groups and therefore
Tim Waugh f80a31
+	    # the call above does not kill anything, kill at least $pid
Tim Waugh f80a31
+	    kill($killsignal, $pid);
Tim Waugh f80a31
 	}
Tim Waugh f80a31
-	$docgeneratorpid = 0;
Tim Waugh f80a31
-    }
Tim Waugh f80a31
 
Tim Waugh f80a31
-    # Close the file converter (if it was used)
Tim Waugh f80a31
-    if ($fileconverterpid) {
Tim Waugh f80a31
+	# Close the documentation page generator (if it was used)
Tim Waugh f80a31
+	if ($kid0) {
Tim Waugh f80a31
+	    print $logh "Killing process $kid0 (KID0) with signal $killsignal\n";
Tim Waugh f80a31
+	    kill($killsignal, $kid0);
Tim Waugh f80a31
+	}
Tim Waugh f80a31
+	
Tim Waugh f80a31
+	# Close the file converter (if it was used)
Tim Waugh f80a31
 	if ($kid2) {
Tim Waugh f80a31
-	    print $logh "Killing process $kid2 (KID2)\n";
Tim Waugh f80a31
-	    kill(9, $kid2);
Tim Waugh f80a31
+	    print $logh "Killing process $kid2 (KID2) with signal $killsignal\n";
Tim Waugh f80a31
+	    kill($killsignal, $kid2);
Tim Waugh f80a31
 	}
Tim Waugh f80a31
 	if ($kid1) {
Tim Waugh f80a31
-	    print $logh "Killing process $kid1 (KID1)\n";
Tim Waugh f80a31
-	    kill(9, $kid1);
Tim Waugh f80a31
+	    print $logh "Killing process $kid1 (KID1) with signal $killsignal\n";
Tim Waugh f80a31
+	    kill($killsignal, $kid1);
Tim Waugh f80a31
 	}
Tim Waugh f80a31
-	$fileconverterpid = 0;
Tim Waugh f80a31
-    }
Tim Waugh f80a31
 
Tim Waugh f80a31
-    # Close the renderer
Tim Waugh f80a31
-    if ($rendererpid) {
Tim Waugh f80a31
+	# Close the renderer
Tim Waugh f80a31
 	if ($kid4) {
Tim Waugh f80a31
-	    print $logh "Killing process $kid4 (KID4)\n";
Tim Waugh f80a31
-	    kill(9, $kid4);
Tim Waugh f80a31
+	    print $logh "Killing process $kid4 (KID4) with signal $killsignal\n";
Tim Waugh f80a31
+	    kill($killsignal, $kid4);
Tim Waugh f80a31
 	}
Tim Waugh f80a31
 	if ($kid3) {
Tim Waugh f80a31
-	    print $logh "Killing process $kid3 (KID3)\n";
Tim Waugh f80a31
-	    kill(9, $kid3);
Tim Waugh f80a31
+	    print $logh "Killing process $kid3 (KID3) with signal $killsignal\n";
Tim Waugh f80a31
+	    kill($killsignal, $kid3);
Tim Waugh f80a31
 	}
Tim Waugh f80a31
-	$rendererpid = 0;
Tim Waugh f80a31
+
Tim Waugh f80a31
+	# Wait some time for the processes to close
Tim Waugh f80a31
+	sleep(5 - $kidgeneration) if $killsignal != 9;
Tim Waugh f80a31
     }
Tim Waugh f80a31
 
Tim Waugh f80a31
-    print $logh "Process dying with \"$message\", exit stat: $exitstat\n\terror: $errmsg ($errcod)\n";
Tim Waugh f80a31
-    if ($spooler eq 'ppr_int') {
Tim Waugh f80a31
-	# Special error handling for PPR intefaces
Tim Waugh f80a31
-	$message =~ s/\\/\\\\/;
Tim Waugh f80a31
-	$message =~ s/\"/\\\"/;
Tim Waugh f80a31
-	my @messagelines = split("\n", $message);
Tim Waugh f80a31
-	my $firstline = "TRUE";
Tim Waugh f80a31
-	for my $line (@messagelines) {
Tim Waugh f80a31
-	    modern_system("lib/alert $printer $firstline \"$line\"");
Tim Waugh f80a31
-	    $firstline = "FALSE";
Tim Waugh f80a31
+    # Do the debug dump and the PPR error handling only from the main process
Tim Waugh f80a31
+    if ($kidgeneration == 0) { # We are the main process
Tim Waugh f80a31
+
Tim Waugh f80a31
+	if ($spooler eq 'ppr_int') {
Tim Waugh f80a31
+	    # Special error handling for PPR intefaces
Tim Waugh f80a31
+	    $message =~ s/\\/\\\\/;
Tim Waugh f80a31
+	    $message =~ s/\"/\\\"/;
Tim Waugh f80a31
+	    my @messagelines = split("\n", $message);
Tim Waugh f80a31
+	    my $firstline = "TRUE";
Tim Waugh f80a31
+	    for my $line (@messagelines) {
Tim Waugh f80a31
+		modern_system("lib/alert $printer $firstline \"$line\"");
Tim Waugh f80a31
+		$firstline = "FALSE";
Tim Waugh f80a31
+	    }
Tim Waugh f80a31
+	} else {
Tim Waugh f80a31
+	    print STDERR $message . "\n";
Tim Waugh f80a31
+	}
Tim Waugh f80a31
+	if ($debug) {
Tim Waugh f80a31
+	    use Data::Dumper;
Tim Waugh f80a31
+	    local $Data::Dumper::Purity=1;
Tim Waugh f80a31
+	    local $Data::Dumper::Indent=1;
Tim Waugh f80a31
+	    print $logh Dumper($dat);
Tim Waugh f80a31
 	}
Tim Waugh f80a31
-    } else {
Tim Waugh f80a31
-	print STDERR $message . "\n";
Tim Waugh f80a31
-    }
Tim Waugh f80a31
-    if ($debug) {
Tim Waugh f80a31
-	use Data::Dumper;
Tim Waugh f80a31
-	local $Data::Dumper::Purity=1;
Tim Waugh f80a31
-	local $Data::Dumper::Indent=1;
Tim Waugh f80a31
-	print $logh Dumper($dat);
Tim Waugh f80a31
     }
Tim Waugh f80a31
+
Tim Waugh f80a31
+    ## The End
Tim Waugh f80a31
+    print $logh "${added_lf}Closing foomatic-rip.\n";
Tim Waugh f80a31
+    close $logh;
Tim Waugh f80a31
+
Tim Waugh f80a31
     exit $exitstat;
Tim Waugh f80a31
 }
Tim Waugh f80a31
 
Tim Waugh f80a31
 # Signal handling routines
Tim Waugh f80a31
 
Tim Waugh f80a31
+sub do_nothing {
Tim Waugh f80a31
+}
Tim Waugh f80a31
+
Tim Waugh f80a31
+sub set_exit_canceled {
Tim Waugh f80a31
+    $retval = $EXIT_PRINTED;
Tim Waugh f80a31
+    rip_die ("Caught termination signal: Job canceled", $retval);
Tim Waugh f80a31
+}
Tim Waugh f80a31
+
Tim Waugh f80a31
+sub set_exit_error {
Tim Waugh f80a31
+    $retval = $EXIT_SIGNAL;
Tim Waugh f80a31
+    rip_die ("Caught error signal: Error in renderer, driver, or foomatic-rip", $retval);
Tim Waugh f80a31
+}
Tim Waugh f80a31
+
Tim Waugh f80a31
 sub set_exit_prnerr {
Tim Waugh f80a31
     $retval = $EXIT_PRNERR;
Tim Waugh f80a31
 }
Tim Waugh f80a31
@@ -6592,20 +6646,36 @@ sub read_attribute_file {
Tim Waugh f80a31
 sub modern_system {
Tim Waugh f80a31
     my (@list) = @_;
Tim Waugh f80a31
 
Tim Waugh f80a31
-    if (($modern_shell =~ /.+/) && ($modern_shell ne '/bin/sh')) {
Tim Waugh f80a31
-        # a "modern" shell other than the default shell was specified
Tim Waugh f80a31
-        my $pid = fork();
Tim Waugh f80a31
-
Tim Waugh f80a31
-        ($pid < 0) && die "failed to fork()";
Tim Waugh f80a31
-
Tim Waugh f80a31
-        if ($pid == 0) {  # child, execute the commands under a modern shell
Tim Waugh f80a31
-            exec($modern_shell, "-c", @list);
Tim Waugh f80a31
-            die "exec($modern_shell, \"-c\", @list);";
Tim Waugh f80a31
-        } else {  # parent, wait for the child
Tim Waugh f80a31
-            waitpid($pid, 0);
Tim Waugh f80a31
-        }
Tim Waugh f80a31
-    } else {  # the system shell is "modern" enough.
Tim Waugh f80a31
-        system(@list);
Tim Waugh f80a31
+    if ($modern_shell |~ /.+/) {
Tim Waugh f80a31
+        # No "modern" shell other than the default shell was specified
Tim Waugh f80a31
+	$modern_shell = '/bin/sh';
Tim Waugh f80a31
+    }
Tim Waugh f80a31
+
Tim Waugh f80a31
+    my $pid = fork();
Tim Waugh f80a31
+    ($pid < 0) && die "failed to fork()";
Tim Waugh f80a31
+
Tim Waugh f80a31
+    if ($pid == 0) {  # child, execute the commands under a modern shell
Tim Waugh f80a31
+	# If the system supports process groups, we create a process
Tim Waugh f80a31
+	# group of this subshell process. All the children of this
Tim Waugh f80a31
+	# process (calls of external filters, renderers, or drivers)
Tim Waugh f80a31
+	# will be members of this process group and so by killing this
Tim Waugh f80a31
+	# process group we can kill all subprocesses and so we can
Tim Waugh f80a31
+	# cleanly cancel print jobs
Tim Waugh f80a31
+	eval("setpgrp()");
Tim Waugh f80a31
+	# Stop catching signals
Tim Waugh f80a31
+	#use sigtrap qw(die normal-signals error-signals
Tim Waugh f80a31
+        #               handler do_nothing USR1 USR2 TTIN);
Tim Waugh f80a31
+	exec($modern_shell, "-c", @list);
Tim Waugh f80a31
+	rip_die("exec($modern_shell, \"-c\", @list);",
Tim Waugh f80a31
+		$EXIT_PRNERR_NORETRY_BAD_SETTINGS);
Tim Waugh f80a31
+    } else { # parent, register child's PID, wait for the child, and
Tim Waugh f80a31
+	     # unregister the PID
Tim Waugh f80a31
+	$pids{$pid} = substr(join(" ", @list), 0, 100) .
Tim Waugh f80a31
+	    (length(join(" ", @list)) > 100 ? "..." : "");
Tim Waugh f80a31
+	print $logh "Starting process $pid: \"$pids{$pid}\"\n";
Tim Waugh f80a31
+	waitpid($pid, 0);
Tim Waugh f80a31
+	print $logh "Process $pid ending: \"$pids{$pid}\"\n";
Tim Waugh f80a31
+	delete $pids{$pid};
Tim Waugh f80a31
     }
Tim Waugh f80a31
 }
Tim Waugh f80a31