A friend came to me with a problem regarding multiple generations (levels) of child processes when forking that has stumped my poor store of information, and so I present the query to thee, hoping to increase in knowledge to answer. The questions follow the background information below.
My friend is writing a client-server process that involves multiple levels of children. While I am not privy to the internals of the project, I can provide the following basic information on the flow, which he agreed to allow me to post.
- Level 0 is the process run from the command-line, which waits for a connection, gets the request, and hands it to a level 1 child for processing. This level should also be the only one to handle updating the data store (which I believe may currently be a tied hash).
- Level 1 is a process which looks for data locally to respond to the request, and if necessary may spawn multiple level 2 children to look data up from other systems. Because of time constraints, and because some of these systems may be unavailable or heavily loaded, this child should only wait for the first responding level 2 child before responding to the request, then reap the remaining level 2 children, and pass back update information to the level 0 parent if necessary.
- Level 2 is a process which makes a request to an external system. It should respond back with the data it receives in response to the query, or a code indicating that the external system was unavailable.
How to prevent the SIGCHLD resulting from the exit of a level 2 child from being seen by the level 0 (grand)parent? It was my guess to redefine the handler routine pointed to for SIGCHLD, but is there anything at that point that could cause the signal to be propagated back to the level 0 process, other than the possibility it might be the last of the level 2 processes being waited upon by the level 1 process that spawned them? I would think in that case it would be a different instance of SIGCHLD.
How can the data from a level 2 child best be returned to its level 1 parent without blocking the parent from getting the data from another child responding quicker? Or from the level 1 child to the level 0 (grand)parent without blocking it from responding to further incoming requests? Could/should either of these be handled in the SIGCHLD handler(s)? From the way it was described, it seems as if there is the possibility that a large number of level 1 children might at times exist, each spawning a number of level 2 children, so I would be concerned that using pipe() or the forking form of open() might resulting in opening too many file handles, and I am not sure what OS this may be loaded on (various forms of *nix certainly, although I think there was mentioned the possibility it might be run on some form of Windows, or possibly other systems as well), so I am not sure IPC::Shareable would be an option either.
Would it be possible for the SIGCHLD handler defined at a particular parent-child level (0-1 or 1-2) to be able to interact with or initiate changes in data that that parent level (0 or 1, respectively)?
Any wisdom and/or instruction in these matters would be greatly appreciated.