I'm trying to implement a little cheat in my code. I want the send some information to the calling application, then tell him to close, then cary on the script doing stuff. That way the app that calls my script thinks it went faster then it really is.
I'm using the Connection: Close trick.
in my perl script I write:
Content-Type: Text/html
Connection: close
Content-Length: 5
22222
this works perfectly if the caller application is a webbrowser that understands Connection: Close it works great. But with an application that does not... well It waits for the script to end.
I tried using close(STDOUT). It works, but the scripts dies shortly after the close statement and does not complete.
How do I do this?
Basicaly, the question is, how do I close STDOUT without killing my process?
BlakMonk
Well, this is one case sniffing won't help.
See, the Connection: Close is defined in the RFC that defines the HTTP protocol. So browsers have to support it. It helps speed web sessions. The browser does not have to wait for the socket to be closed, it simply reads the number of characters specified by Content-Lenth then closes the connection.
I cannot modify the calling applications, I can only modify my application. Since it's cgi/perl and not mod_perl It (the script) doesn't can't really talk to the httpd (not that I know of).
Closing the STDOUT is the only think I can think of. But when I close STDOUT, the parent process (HTTPD) thinks the child is done, then cleans up after itself, thus killing the script. Which is perfectly logical.
I don't know how to bypass that yet.
BlakMonk
(wish I could answer your original question about how to close STDOUT, but nothing comes to mind; that's why I'm trying to think of alternatives)
I really appreciate the time you take.
Well, sending the rest of the treatemetn to a child process is not really an option. I would have to restart the entire process from scratch. The function I want to cheat on is a bunch of inserts into a database.
I even tried to re-open STDOUT, but it's too late, once it's closed httpd starts the cleaning process.
blakmonk
Why not redirect the user to another page with a Location: ....?
Perhaps this forces the script to close, perhaps the redirection does not take place until the script closes - I don't know.
Perhaps do the same by using a META redirect.
Alternatively, run the script from a small on-click popup or something like that and close the window when it's done. Credit-card clearing companies sometimes do something like this.
Kaled.
exec() terminates the current process for you and doesn't return
The exec() system calls *replace* the current process, not terminate it (behind the scenes, every time you fire off a new process, it's a fork() then an exec())
[perl]
[root@bob root]# cat foo1.c
#include <stdio.h>
void main(void) {
printf("In foo1, pid= %d\n", getpid());
}
[root@bob root]# cat foo2.c
#include <stdio.h>
void main(void) {
printf("In foo2, pid= %d\n", getpid());
printf("execing!\n");
execv("foo1", NULL);
}
[/perl]
[root@bob root]# ./foo2
In foo2, pid= 24300
execing!
In foo1, pid= 24300
The first is pretty easy...
[perl]
if (fork()) {
# parent process
# send out the message here to close the connection
} {
# child process
# do the dirty work
}
[/perl]
Sean
Thank you all for your replies, let me try to replie back in order:
VectorJ:
The daemon to handle the queries is really over kill, since it's not just queries, there is lots of treatment done on the data that is returned by the DB.
Kaled:
You maybe new, but you have good ideas... but! my problem comes from the fact that the client that is reading the response from the web server does not understand the HTTP language. It's a socket application that sends the HTTP request then reads the response blindly.
SeanW:
I understand exec, wil would be great if the work was being done but a sub-process, but it has to be done by the current process. It I could have such a thing as a Self->Exec, something that would fork the running process itself and continue it from where it is crrently... httpd work think that the process would have died. and woulnd try to kill it's children.
SeanW:
Would the fork continue the current process?
BlakMonk
Does it continue from where it is at or from the beginning of the code?
Right after the fork(). That's why it's usually wrapped in the if statement I showed you, ie to determine if you returned in the parent process (in which case fork() returns the child's pid), or if you're in the child process (in which case fork() returns 0)
are the variables transfered on to the child?
Yes, including file descriptors. You may want to close STDIN/STDOUT when in the child process.
And what parent dies, does it take the child with him?
No, init (pid 1) takes on the child process.
I wrote an article about this a while back that might clear it up:
[ertw.com...]
Sean