PDA

View Full Version : child process exits and closes parent's connections



Elkvis
09-04-2009, 08:08 AM
I have a server that spawns a separate process to handle credit card transactions (64-bit server, but the credit card library is only available in 32-bit form), and when the child process ends, it closes the server instance's network connection and database connection because it co-owns the file descriptors that represent those connections. is there any way I can prevent this from happening? I don't care if the child closes its own copies of the descriptors, but it would be nice if I could prevent it from closing the parent's connections.

Kennedy
09-04-2009, 09:16 AM
fd = open("myfile", O_RDWR);
if ((pid = fork()) == 0){
callsomething();
}
callsomethingelse();
return 0;
It is my understanding that in the example above that fd would have been "opened" twice. If, however, you open myfile from within callsomething() or callsomethingelse(), you'd not have a common file descriptor. How is your code written? Does it do the above or does only the child open the database?

Elkvis
09-04-2009, 09:42 AM
Does it do the above or does only the child open the database?

the parent opens the database connection. and when the child exits, it closes that connection.

Kennedy
09-04-2009, 10:02 AM
By that I'm assuming that you mean the parent opens the connection above where you do your fork(). Does the child actually perform a close operation to the connection?

MK27
09-04-2009, 11:30 AM
I'm actually working on a network client right now that needs to share it's connected socket amongst multiple process which are temporary. I'm using pthreads and just made the socket fd a global and this works fine.

If you haven't used pthreads before, it is very very simple to substitute it for fork in this circumstance. You just make your process a function and launch it this way:


pthread_t mythread;
pthread_create(&mythread,NULL,myfunc,NULL);
pthread_detach(mythread);

At the end of myfunc() (which must be void *) you need:


pthread_exit(NULL);


You can pass myfunc initial data (via the last pointer in pthread_create), so you don't even need to use a global if that's an issue.

You could switch over to that sort of model quite easily I think, it would not require many changes, and it gives you some more interesting opportunities too...

Elkvis
09-04-2009, 12:08 PM
By that I'm assuming that you mean the parent opens the connection above where you do your fork(). Does the child actually perform a close operation to the connection?

the parent opens the connection to the database when the request comes in from the client. the child simply inherits it as any child process inherits its parent's open descriptors. the child does not explicitly close it, but the system closes descriptors automatically when the process exits. and because the child's descriptors refer to the same connections as the parent's, it closes the parent's connections as well.

MK27: I can't use pthreads because the credit card processing program runs as a 32-bit process, while the parent is 64-bit, and the credit card processing library is only available as a 32-bit library, so I can't link it into my main program. it has to be a separate process.

MK27
09-04-2009, 12:20 PM
MK27: I can't use pthreads because the credit card processing program runs as a 32-bit process, while the parent is 64-bit, and the credit card processing library is only available as a 32-bit library, so I can't link it into my main program. it has to be a separate process.

Ouch.

Elkvis
09-04-2009, 12:38 PM
Ouch.

I've done my damnedest to get the software vendor to recompile it for 64-bit or to give me the source so I can, but it just isn't going to happen short of my company entering into an NDA and forking (no pun intended) over thousands of dollars.

Valery Reznic
09-04-2009, 10:24 PM
I have a server that spawns a separate process to handle credit card transactions (64-bit server, but the credit card library is only available in 32-bit form), and when the child process ends, it closes the server instance's network connection and database connection because it co-owns the file descriptors that represent those connections. is there any way I can prevent this from happening? I don't care if the child closes its own copies of the descriptors, but it would be nice if I could prevent it from closing the parent's connections.


Did child need those or any other file descriptors from parents at all ?

If not - and assuming your are using Linux (who use something else for servers anyway :)
you can instead of fork use clone with flag CLONE_FILES turn off
In this case parent and child will not share file descriptors.

If child really uses some file descriptors from parent, then turning of CLONE_FILES is not an option.
In this case you can write small shared libraries and run your child process with this libraries LD_PRELOADed.

Shared library should implement 'close' function. Those function should do nothing for
network connection and database connection file descriptors and behaves like original close for any other

Elkvis
09-06-2009, 06:03 AM
Did child need those or any other file descriptors from parents at all ?

If not - and assuming your are using Linux (who use something else for servers anyway :)
you can instead of fork use clone with flag CLONE_FILES turn off
In this case parent and child will not share file descriptors.

If child really uses some file descriptors from parent, then turning of CLONE_FILES is not an option.
In this case you can write small shared libraries and run your child process with this libraries LD_PRELOADed.

Shared library should implement 'close' function. Those function should do nothing for
network connection and database connection file descriptors and behaves like original close for any other

the child has absolutely no need of the socket or the db connection; however, the sticky part of this whole thing is that the parent communicates with the child through a pipe via popen(), so at least SOME file descriptors need to be cloned. unfortunately, I can't choose which ones, so it's all or nothing.

in any case, I've come up with a pretty workable solution to this problem. I'm going to re-write the credit card processor as a standalone server that listens on a unix-domain socket (AF_UNIX) and then I won't have to worry about it. the two processes will be unrelated, and therefore, share no file descriptors, and my problem will magically disappear.

Kennedy
09-08-2009, 02:54 PM
It almost sounds like you need a third process running that communicates with your DB. Let the parent communicate with that process and fork children as necessary. Then the child process doesn't get that opened connection ever.

Elkvis
09-09-2009, 08:28 PM
It almost sounds like you need a third process running that communicates with your DB. Let the parent communicate with that process and fork children as necessary. Then the child process doesn't get that opened connection ever.

close.

the existing server code will run as it always has, and the credit card processing program will be its own standalone server program (the new process) that can listen on a unix-domain socket and handle requests to process card transactions.