Re: Help -- how to fork an Apache process in mod_perl safely? Not Apache2:Subprocess...
William T wrote: There are all kinds of problems that you'll encounter and have to solve if you fork. I found it's better to call at(1) to start another seperate process immediatly. If you need to pass data JSON worked really well for me. Thanks, that's what I ended up doing. First I ended up having to move the processing into an external script call anyway, and then I tried Apache2::SubProcess, and it ended up working, but my script was randomly receiving TERM signals... it's handleable of course, but I decided to go with the 'at' technique, it's safer that way, I suppose. On Aug 25, 2009 5:12 AM, Victor Danilchenko vic...@askonline.net mailto:vic...@askonline.net wrote: Hi all, I need to be able to fork an Apache process in daemon form, to do some housekeeping which might potentially take a few seconds. However, when I do that, I start getting SQL errors (of the connection lost type) in the browser. I do the fairly standard cleanup to daemonize the child process, but of course it needs to retain the SQL socket open. Here is my forking code: sub modperl_kamikaze_fork () { # You will have to do CORE::exit(0) at the end of the execution. $SIG{CHLD} = 'IGNORE'; get_m-flush_buffer; defined (my $kid = fork) or die Cannot fork: $!\n; return $kid if $kid; my $r = get_r; close STDIN; open STDIN, '/dev/null' or die Can't read /dev/null: $!; close STDOUT; open STDOUT, '/dev/null' or die Can't write to /dev/null: $!; close STDERR; open STDERR, '/tmp/form.log' or die Cannot open /tmp/fork.log\n; setsid or die Can't start a new session: $!; my $oldfh = select STDERR; local $| = 1; select $oldfh; warn Child (PID $$) spawned.\n; $r-child_terminate; } The Apache2:Subprocess doesn't help me, because I need not to spawn an external process, but to finish processing in mod_perl context -- just without bugging the user with it. Any ideas on how to either fork better, or how to solve this without forking (e.g. is there a way to 'append' a function call to the request after the rest of the request is completed)? Many thanks in advance. -- Victor Danilchenko Senior Software Engineer, AskOnline.net vic...@askonline.net mailto:vic...@askonline.net - 617-273-0119 -- Victor Danilchenko Senior Software Engineer, AskOnline.net vic...@askonline.net - 617-273-0119
Help -- how to fork an Apache process in mod_perl safely? Not Apache2:Subprocess...
Hi all, I need to be able to fork an Apache process in daemon form, to do some housekeeping which might potentially take a few seconds. However, when I do that, I start getting SQL errors (of the connection lost type) in the browser. I do the fairly standard cleanup to daemonize the child process, but of course it needs to retain the SQL socket open. Here is my forking code: sub modperl_kamikaze_fork () { # You will have to do CORE::exit(0) at the end of the execution. $SIG{CHLD} = 'IGNORE'; get_m-flush_buffer; defined (my $kid = fork) or die Cannot fork: $!\n; return $kid if $kid; my $r = get_r; close STDIN; open STDIN, '/dev/null' or die Can't read /dev/null: $!; close STDOUT; open STDOUT, '/dev/null' or die Can't write to /dev/null: $!; close STDERR; open STDERR, '/tmp/form.log' or die Cannot open /tmp/fork.log\n; setsid or die Can't start a new session: $!; my $oldfh = select STDERR; local $| = 1; select $oldfh; warn Child (PID $$) spawned.\n; $r-child_terminate; } The Apache2:Subprocess doesn't help me, because I need not to spawn an external process, but to finish processing in mod_perl context -- just without bugging the user with it. Any ideas on how to either fork better, or how to solve this without forking (e.g. is there a way to 'append' a function call to the request after the rest of the request is completed)? Many thanks in advance. -- Victor Danilchenko Senior Software Engineer, AskOnline.net vic...@askonline.net - 617-273-0119
Re: Help -- how can I make the Apache process die at the end of the request?
Adam Prime wrote: Victor Danilchenko wrote: I need to do it forcibly, no matter what happens during the request. I have to slightly relax security constraints to call an unusual subrequest, and since I cannot guarantee that the cleanup code will be reached (what if the subrequest is terminated by the client, or dies on a bug?), I figure my best bet it to make sure that at the end of the request execution, the current apache process dies so that a new one can be spawned. 'kill $$' is obviously inadequate. Does anyone have any idea how this can be achieved? perhaps utilizing MaxRequestsPerChild somehow, I could trick the parent process into terminating this one after the request completes? or is there some mod_perl feature which tells mod_perl to not re-use the perl runtime in a given process? Any help and/or ideas are much appreciated. Thanks in advance. $r-child_terminate() mp2: http://perl.apache.org/docs/2.0/api/Apache2/RequestUtil.html#C_child_terminate_ Perfect. Much thanks. -- Victor Danilchenko Senior Software Engineer, AskOnline.net [EMAIL PROTECTED] - 617-273-0119
Help -- how can I make the Apache process die at the end of the request?
I need to do it forcibly, no matter what happens during the request. I have to slightly relax security constraints to call an unusual subrequest, and since I cannot guarantee that the cleanup code will be reached (what if the subrequest is terminated by the client, or dies on a bug?), I figure my best bet it to make sure that at the end of the request execution, the current apache process dies so that a new one can be spawned. 'kill $$' is obviously inadequate. Does anyone have any idea how this can be achieved? perhaps utilizing MaxRequestsPerChild somehow, I could trick the parent process into terminating this one after the request completes? or is there some mod_perl feature which tells mod_perl to not re-use the perl runtime in a given process? Any help and/or ideas are much appreciated. Thanks in advance. -- Victor Danilchenko Senior Software Engineer, AskOnline.net [EMAIL PROTECTED] - 617-273-0119
Re: A question about wiring up filehandles for direct dump to HTTP pipe
Michael Peters wrote: Victor Danilchenko wrote: Is there any way, to, uhhh, tell Apache programatically to simply slurp up the file from an open filehandle I could be wrong, but I doubt you can pass a Perl file handle to a C program that is not Perl aware (like Apache). I am hoping you are wrong, but I am not expecting it. To be honest, I kinda figured that there would be no easy and perfect way around it. or to grab a given file from disk? Doing a redirect to the real location is less than ideal precisely because that will open a door to the circumvention of this accounting script, a door which will be rather hard to close. What about an internal redirect? It won't expose where the door is and you can make it such that access to that URL is forbidden to any request not coming from your machine. Huh, I didn't even realize this was possible. $r-internal-redirect, eh? That sounds just like what I need -- coupled with some form of hotlink protection, it should do the job. Thanks a lot. But the best approach seems to convert your code into an Apache Authen or Authz handler to do all the book keeping. Then simply let Apache continue with the processing after that. You'd probably have to ditch Mason for that piece of the code, but it's pretty straight forward. If you are familiar with Apache internals, I am sure it is. i am not. Unfortunately, this happens to be one of those the roof is on fire deals -- I have to not only solve this problem, but solve it *fast*. Many thanks for your immensely helpful advice. I think the internal redirect is close enough to what I need to be useful. once again, thanks. -- Victor Danilchenko Senior Software Engineer, AskOnline.net [EMAIL PROTECTED] - 617-273-0119
Re: A question about wiring up filehandles for direct dump to HTTP pipe
This solution ended up being perfect, and SIMPLE. I just had to sprinkle a little Mime::FileInfo::Magic over the request, to get the content-type to work right, and POOF! it worked. Just like that. My entire wrapper code (without the accounting, ACL, and somesuch stuff) is under 10 lines, and half of it is constructing the 404 responder. Torsten Foertsch wrote: On Fri 22 Feb 2008, Victor Danilchenko wrote: or to grab a given file from disk? Perhaps $r-sendfile($filename)? Defined in Apache2::RequestIO. -- Victor Danilchenko Senior Software Engineer, AskOnline.net [EMAIL PROTECTED] - 617-273-0119
Re: Help with sending custom headers in mod_perl2
Perrin Harkins wrote: On 5/2/07, Victor Danilchenko [EMAIL PROTECTED] wrote: I seem to be missing something very obvious... I have: $r-header_out(Refresh=0; URL=$uri\n); I think you're looking for this: $r-headers_out-add(Refresh=0; URL=$uri\n); Yup, that was it. Thanks. Unfortunately, it worked, but it didn't help :(. Apparently neither Firefox nor IE honor the Refresh HTTP header when performing the XMLHttpRequest operation in JavaScript, so I will have to figure out a different way to re-process the request upon error. You were trying to use mod_perl 1 syntax. See this for more: http://perl.apache.org/docs/2.0/user/porting/compat.html#C__r_E_gt_header_out_ -- | Victor Danilchenko | Give a man a match, and he will be warm | | [EMAIL PROTECTED] | for a moment; but set him on fire, and| | CSCF | 5-4231 | he will be warm for the rest of his life. |
Re: Help with sending custom headers in mod_perl2
Someone (you know who you are, thanks!) helped me off-list by pointing out that I should use HTTP status 301 with Location header instead. In retrospect, it should have been obvious that the behavior I desired is meaningless in the context of Refresh header. D'oh. Victor Danilchenko wrote: Perrin Harkins wrote: On 5/2/07, Victor Danilchenko [EMAIL PROTECTED] wrote: I seem to be missing something very obvious... I have: $r-header_out(Refresh=0; URL=$uri\n); I think you're looking for this: $r-headers_out-add(Refresh=0; URL=$uri\n); Yup, that was it. Thanks. Unfortunately, it worked, but it didn't help :(. Apparently neither Firefox nor IE honor the Refresh HTTP header when performing the XMLHttpRequest operation in JavaScript, so I will have to figure out a different way to re-process the request upon error. You were trying to use mod_perl 1 syntax. See this for more: http://perl.apache.org/docs/2.0/user/porting/compat.html#C__r_E_gt_header_out_
Re: Help with $r being corrupted
Perrin Harkins wrote: On 5/2/07, Victor Danilchenko [EMAIL PROTECTED] wrote: I suspect this is a Perl issue, as I have noticed that generally, funny things seem to occasionally happen with the symbol table (i.e. methods getting forgotten ever once in a while) in the perl code. I don't think it's a general perl issue. Probably there is a bug in some C code, either in a module you're using or in mod_perl, that is causing this problem. If you can figure out a way to reproduce it reliably, it can be fixed. I wish it were so easy. As it is, all I have now is perhaps a dozen error instances per many thousands of requests (each day). I trap the error in eval and mail it to myself, though, so if you have any suggestions about the extra data to include in the mailed message, for debugging purposes, I would be glad to hear it. This problem has been bugging me like crazy.
Re: Help with $r being corrupted
I am not sure if it's the same type of error, but the idea of recording the PID is a great one -- if it is the problem, then forcing the error-prone child to commit suicide might indeed be the answer. I will add it to the error reporting. Adam Prime x443 wrote: I have encounter the same problem (at least the same symptoms) thread here: http://marc.info/?l=apache-modperlm=114226565622372w=2 I have never been able to find a true solution, but it is very intermittent. I worked around it by doing this (which isn't really a solution at all, and in fact borders on horrible). It does however keep the user from getting a 500 (they get nothing at all instead). I kill the child because the errors would usually come in clusters all from a single apache child. sub handler { my $r = shift; if ( !ref($r) || (ref($r) ne 'Apache' ref($r) ne 'Apache::Request' ref($r) ne 'Apache::Filter')){ print STDERR 'pnotes error occuring '.__PACKAGE__.' - pid: ' . $$ . ' non-apache object: ' . ref($r) . \n; Apache-request-child_terminate; return DONE; } ... You might be able to work around it by doing something like this though now that i think about it. sub handler { my $r = shift; if ( !ref($r) || (ref($r) ne 'Apache' ref($r) ne 'Apache::Request' ref($r) ne 'Apache::Filter')){ $r = Apache-request; $r-child_terminate; # i'd still kill off the child anyway } HTH Adam -Original Message- From: Victor Danilchenko [mailto:[EMAIL PROTECTED] Sent: Thursday, May 03, 2007 6:51 PM To: Frank Wiles Cc: modperl@perl.apache.org Subject: Re: Help with $r being corrupted Frank Wiles wrote: Actually it isn't an issue of methods being forgotten, more likely you aren't using Apache2::RequestUtil in your code. Preferably preloading it. Well, the production code which has this problem is running under mod_perl 1 and Apache 1.3 right now, but I do load both Apache and Apache::Request there (the code is compatible with moth mod_perl and mod_perl2, I also load Apache2::RequestUtil in the Apache2 comaptibility block), and the error still occurs. Is it some different module for Apache 1 that I am missing? Though the fact that the error occurs only infrequently, and mostly in requests which occur over SSL, makes me suspect that it's something else.
Re: Help with $r being corrupted
Frank Wiles wrote: Actually it isn't an issue of methods being forgotten, more likely you aren't using Apache2::RequestUtil in your code. Preferably preloading it. Well, the production code which has this problem is running under mod_perl 1 and Apache 1.3 right now, but I do load both Apache and Apache::Request there (the code is compatible with moth mod_perl and mod_perl2, I also load Apache2::RequestUtil in the Apache2 comaptibility block), and the error still occurs. Is it some different module for Apache 1 that I am missing? Though the fact that the error occurs only infrequently, and mostly in requests which occur over SSL, makes me suspect that it's something else.
Help with sending custom headers in mod_perl2
I seem to be missing something very obvious... I have: $r-header_out(Refresh=0; URL=$uri\n); $r-send_http_header; print Test redirect = $uri\n; But when the redirect page gets submitted, the HTTP headers show up as page contents: Keep-Alive: timeout=15, max=99 Connection: Keep-Alive Transfer-Encoding: chunked Content-Type: text/html; charset=UTF-8 1e Test redirect = /?loopback=1 0 Obviously only the stuff after 'Test redirect' should show up. I am using Mason, and writing an error handler -- it tries to tell the browser resubmit a GET request in the event of a Mason failure. It looks like Mason inserts a blank line to terminate the HTTP header block. is there any way to counter that, so that the header directives end up in the header? Incidentally, the actual Refresh header does work, so maybe my hypothesis about Mason is off the wall. Any ideas? P.S. On a wild shot, does anyone know if the XMLHttpRequest JavaScript directive generally honors the HTTP Refresh header in Firefox and IE?
Help with $r being corrupted
Hi all, I have a custom handler which is supposed to do some stuff with the request, and run it through the Mason parser. The trouble is that ever once in a while -- rarely -- the request object comes to my handler method corrupted. The error I usually get is that dir_config method is not defined for $r: Can't locate object method dir_config via package Ask::Mason::Secure at /usr/share/perl5/HTML/Mason/ApacheHandler.pm line 895. I tracked it down, and it is the $r problem. I suspect this is a Perl issue, as I have noticed that generally, funny things seem to occasionally happen with the symbol table (i.e. methods getting forgotten ever once in a while) in the perl code. So, I was wondering if there is any way to reconstitute the object, to get a new $r variable within the handler -- to re-create the Apache2::RequestRec object really. Can anyone help out with an idea?
Re: Help with sending custom headers in mod_perl2
By the way, this submission of the HTTP header also seems to result in an about 20 second additional delay on the client side -- i.e. if I request an object which returns the Refresh header, I wait for about 20 seconds, then see the headers flash by as page contents, and then the refresh occurs. I do not get this extra delay when I simply submit the refresh as a meta header, so this seems to be an artifact of the HTTP transaction in some way. Victor Danilchenko wrote: I seem to be missing something very obvious... I have: $r-header_out(Refresh=0; URL=$uri\n); $r-send_http_header; print Test redirect = $uri\n; But when the redirect page gets submitted, the HTTP headers show up as page contents: Keep-Alive: timeout=15, max=99 Connection: Keep-Alive Transfer-Encoding: chunked Content-Type: text/html; charset=UTF-8 1e Test redirect = /?loopback=1 0 Obviously only the stuff after 'Test redirect' should show up. I am using Mason, and writing an error handler -- it tries to tell the browser resubmit a GET request in the event of a Mason failure. It looks like Mason inserts a blank line to terminate the HTTP header block. is there any way to counter that, so that the header directives end up in the header? Incidentally, the actual Refresh header does work, so maybe my hypothesis about Mason is off the wall. Any ideas? P.S. On a wild shot, does anyone know if the XMLHttpRequest JavaScript directive generally honors the HTTP Refresh header in Firefox and IE?