in reply to inetd spawned perl problem

I am presuming that the commands you are running via remsh are _not_ trying to read STDIN. If they did, they would detect EOF when the remote process ended (or otherwise closed the socket), so they should exit normally.

Assuming this is the case, you should have a process use select() or IO::Select::can_read to monitor the socket. Without knowing which O/S and version of Perl you are running this on, I can't promise this will work, but my suggestion would be to try this:

Right before you do the open(RCMD,...), fork(). Have the parent do a can_read on STDIN. Have it be prepared to receive SIGCHLD. The child just runs the code that you give above, then exits().
If the can_read() returns before the SIGCHLD, then the socket has closed (assuming you are not expecting more data!) and you can kill the child process.

Replies are listed 'Best First'.
Re: Re: inetd spawned perl problem
by vasu (Novice) on May 09, 2003 at 16:47 UTC
    Hi, Thank you very much for your message. I'm using perl 5.005_03 on HP-UX 10.20 and 5.8.0 on Tru64 v5. I think that i've not explained the exact problem.
    The connection sequence would be as shown:
    • client uses telnet to make connection to inetd port (eg 9876)
    • inetd spawns my perl process and disassociates itself from the active socket created. My perl process does not explicitly open a socket; all it's doing is writing to stdout, which in turn will be written on the socket back to the client.
    • My perl process runs remsh and writes whatever data is returned by remsh.

    At this point, I close the client that calls the telnet. If I start remsh w/o the -n option, then the spawned child remsh process becomes defunct (most probably b'cos the parent remsh process does not do a wait()). If I start remsh with the -n option, then there does not appear to be any signals processed (additionally remsh inherently ignores TERM, INT and QUIT).
    So, at this point, I have my perl script still running along with the remsh processes. The script will exit along with the remsh processes only when there is some data returned from remsh and SIGPIPE is received.
    Is there any other way I can check for the closure of the socket from my perl script (given the fact that I dont have a file handle on the socket) ? Also, any other way I can check for the closure of STDOUT ? I cant write arbitrary data out to STDOUT as the script writes to another set of processes that parse the data and expect the data to be in a certain format and those processes cannot be modified easily.
    Thanks again!
      Here is my interpretation of what you describe:

      A client process "C" connects to port 9876.
      Inetd accepts the connection, forks, then execs() your perl program "P".
      Your perl program starts a remsh process "S" which connects to a remote host and process "R".

      The process P is running this code:

      open(RCMD, "remsh $h -l $u $script |") || die $!; while (<RCMD>) { print $_; }

      I think what you are asking is how your Perl program P can detect if the client C exits (or otherwises closes the socket connection). Right now it may wait a long time on <RCMD> and not give an error until the "print $_".

      If this is a correct understanding, then what I suggested above should work. The STDIN and STDOUT of your Perl process P are both connected to the socket connection that "C" connected to and inetd accepted. A call to select() or can_read() should detect when that socket connection is closed.

        Thank you very much for your pointers. The problem was solved by following your suggestions. The new code looks like:
        while (! eof(RCMD)) { my @fds = $sel->can_read(5); #print NSY "FDS = @fds\n"; if ($#fds == 0) { my $in = <RCMD>; print $in; } else { my @fds = $wsel->can_read(0); #print NSY "FDS = @fds\n"; if ($#fds != 0) { #print NSY "Closing as stdout closed\n"; exit(0); } } }