[interchange-cvs] interchange - jon modified 2 files

interchange-cvs at icdevgroup.org interchange-cvs at icdevgroup.org
Fri Dec 19 04:47:43 UTC 2008


User:      jon
Date:      2008-12-19 04:47:42 GMT
Modified:  code/UserTag child-process.tag
Modified:  lib/Vend Server.pm
Log:
Fix design flaw in the new child-process tag:

* Need to double-fork and close sockets and filehandles to disconnect from
the parent process so that the parent doesn't wait for the child to finish.

* Add a new routine &Vend::Server::cleanup_for_exec to handle clearing the
private socket variables, usable from other child code as well.

* Can no longer return a useful PID because of the double-fork, so return
nothing from the tag.

Some other tweaks as well:

* Change process description and allow it to be customized, especially
useful for long-running processes.

* Don't bother retrying if fork attempts fail, as that gets prohibitively
complicated on double-forks and probably indicates a suffocating system
we shouldn't add load to anyway.

* For now, at least, don't bother with optional single-fork implementation
which is mostly useful for a tiny bit of improved performance that's not
worth the hassle for a background process.

* Ignore not just an empty body, but also one with only whitespace.

* Remove documentation for unimplemented umask option.

Revision  Changes    Path
1.2                  interchange/code/UserTag/child-process.tag


rev 1.2, prev_rev 1.1
Index: child-process.tag
===================================================================
RCS file: /var/cvs/interchange/code/UserTag/child-process.tag,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -u -r1.1 -r1.2
--- child-process.tag	14 Dec 2008 10:06:04 -0000	1.1
+++ child-process.tag	19 Dec 2008 04:47:42 -0000	1.2
@@ -1,15 +1,17 @@
-# Copyright 2002-2007 Interchange Development Group and others
+# Copyright 2008 Interchange Development Group and others
 # 
 # This program is free software; you can redistribute it and/or modify
 # it under the terms of the GNU General Public License as published by
 # the Free Software Foundation; either version 2 of the License, or
 # (at your option) any later version.  See the LICENSE file for details.
 # 
-# $Id: child-process.tag,v 1.1 2008-12-14 10:06:04 ton Exp $
+# $Id: child-process.tag,v 1.2 2008-12-19 04:47:42 jon Exp $
 
 UserTag child-process addAttr
 UserTag child-process HasEndTag
-UserTag child-process Version $Revision: 1.1 $
+UserTag child-process NoReparse 0
+UserTag child-process Interpolate 0
+UserTag child-process Version $Revision: 1.2 $
 UserTag child-process Documentation <<EOD
 
 =head1 NAME
@@ -25,6 +27,8 @@
 Runs Interchange markup code in a forked child process.
 Useful for off-loading processes that take a relatively long time to complete.
 
+Has no effect if the body is empty or contains only whitespace.
+
 Options are:
 
 =over 4
@@ -34,6 +38,11 @@
 File name relative to catalog directory to file where output from forked
 process should be stored.
 
+=item label
+
+Optional descriptive label for this process that will be put in the operating
+system process list. Default is "child-process tag".
+
 =item notifyname
 
 File name relative to catalog directory where a file of zero length will
@@ -44,18 +53,14 @@
 in web docroot space one could poll for the existence of this file and
 when it exists bounce to a page that will display the results.
 
-=item umask
-
-Octal umask for notification file.
-
 =back
 
 =head1 EXAMPLES
 
  This is the parent process.
 
- Child process starts here:<br>
- Child PID: [child-process filename="tmp/report_[time]%Y%m%d%H%M%S[/time].txt"]
+ Child process starts here.
+ [child-process filename="tmp/report_[time]%Y%m%d%H%M%S[/time].txt"]
  [query
      list=1
      sql="
@@ -79,55 +84,47 @@
 
 EOD
 UserTag child-process Routine <<EOR
+
+use POSIX ();
+
 sub {
-	my ($opt, $body) = @_;
-	use vars qw/ $Tag /;
+    my ($opt, $body) = @_;
+    use vars qw/ $Tag /;
 
-	return unless defined($body) and length($body);
+    return unless defined($body) and $body =~ /\S/;
 
-	my $pid;
+    defined(my $kid = fork) or die "Cannot fork: $!\n";
+    if ($kid) {
+        waitpid($kid, 0);
+        return;
+    }
+    else {
+        defined (my $grandkid = fork) or die "Kid cannot fork: $!\n";
+        exit if $grandkid;
+
+        Vend::Server::cleanup_for_exec();
+
+        # Disconnect from parent's terminal
+        POSIX::setsid() or die "Can't start a new session: $!\n";
+
+        defined $opt->{label} or $opt->{label} = 'child-process tag';
+        Vend::Server::set_process_name($opt->{label});
+
+        my $output = interpolate_html($body, 1);
+
+        my $filename = $opt->{filename};
+        if (defined($filename) and length($filename)) {
+            $filename = $Tag->filter('filesafe', $filename);
+            my $status = $Tag->write_relative_file($filename, $$output);
+
+            my $notifyname = $opt->{notifyname};
+            if ($status and defined($notifyname) and length($notifyname)) {
+                $notifyname = $Tag->filter('filesafe', $notifyname);
+                $Tag->write_relative_file($notifyname, $opt, '');
+            }
+        }
 
-	FORK: {
-		if ($pid = fork) {
-			# Parent
-			# As parent we have no tasks to perform at this place
-			# we only want to off-load 'heavy' processes to a child process
-			# The main reason for this Usertag
-
-			return $pid;
-		}
-		elsif (defined $pid) {
-			# Child
-
-			Vend::Server::reset_per_fork();
-
-			my $output = interpolate_html($body, 1);
-			if (defined($$output) and length($$output)) {
-				my $filename = $opt->{filename};
-				if (defined($filename) and length($filename)) {
-					$filename = $Tag->filter('filesafe', $filename);
-					my $status = $Tag->write_relative_file($filename, $$output);
-
-					my $notifyname = $opt->{notifyname};
-					if ($status and defined($notifyname) and length($notifyname)) {
-						$notifyname = $Tag->filter('filesafe', $notifyname);
-						$Tag->write_relative_file($notifyname, $opt, '');
-					}
-
-				}
-			}
-
-			exit;
-		}
-		elsif ($! =~ /No more process/) {
-			# Supposedly recoverable fork error
-			select(undef, undef, undef, 2.00);
-			redo FORK;
-		}
-		else {
-			# Weird fork error
-			die "Can't fork: $!\n";
-		}
-	}
+        exit;
+    }
 }
 EOR



2.95                 interchange/lib/Vend/Server.pm


rev 2.95, prev_rev 2.94
Index: Server.pm
===================================================================
RCS file: /var/cvs/interchange/lib/Vend/Server.pm,v
retrieving revision 2.94
retrieving revision 2.95
diff -u -u -r2.94 -r2.95
--- Server.pm	19 Dec 2008 04:37:44 -0000	2.94
+++ Server.pm	19 Dec 2008 04:47:42 -0000	2.95
@@ -1,6 +1,6 @@
 # Vend::Server - Listen for Interchange CGI requests as a background server
 #
-# $Id: Server.pm,v 2.94 2008-12-19 04:37:44 jon Exp $
+# $Id: Server.pm,v 2.95 2008-12-19 04:47:42 jon Exp $
 #
 # Copyright (C) 2002-2008 Interchange Development Group
 # Copyright (C) 1996-2002 Red Hat, Inc.
@@ -26,7 +26,7 @@
 package Vend::Server;
 
 use vars qw($VERSION);
-$VERSION = substr(q$Revision: 2.94 $, 10);
+$VERSION = substr(q$Revision: 2.95 $, 10);
 
 use Cwd;
 use POSIX qw(setsid strftime);
@@ -3074,6 +3074,25 @@
     return;
 }
 
+# Disconnect child process from any dangling attachments to parent process.
+# Named after similar mod_perl routine.
+sub cleanup_for_exec {
+    # Release any open sockets
+    %fh_map = %vec_map = %s_vec_map = %s_fh_map = %ipc_socket = %unix_socket
+        = ();
+
+    # Close filehandles except for STDERR, used for debug log
+    close MESSAGE;
+    close SOCK;
+    open STDIN, '<', '/dev/null';
+    open STDOUT, '>>', '/dev/null';
+
+    # Clear any cached DBI handles
+    reset_per_fork();
+
+    return;
+}
+
 
 1;
 __END__







More information about the interchange-cvs mailing list