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