seaver has asked for the wisdom of the Perl Monks concerning the following question:

Dear All

Following a recent thread, I managed to put together a daemon that works, in the sense that it returns '0' while running an external process using 'exec()'

$SIG{CHLD}=sub { wait(); print "Child exited\n";}; $| = 1; exec("/usr/local/bin/monster", "-i$id", "$filePath$file") unless fork( +); return 0;

The only thing is, if I try to start ANOTHER run at the same time, before the first EXTERNAL process has finished, the 'run' button hangs UNTIL the first process has finished and the CHLD handler returns, and then it runs it. It's basically queuing requests.

Each request is made from an applet i designed that uses XML-RPC, and the daemon is in turn a SOAP::Lite XML-RPC daemon. I need to use this daemon to work as an application server, in the true sense of a server, so that it will be able to accept any request at any time, and immediately run the software.

bottom line is that the above code doesnt do this job, what should i do to make sure that it'll immediately run every request.

thanks

Sam

  • Comment on It works, and then it doesn't...connecting to a daemon over the net
  • Download Code

Replies are listed 'Best First'.
Re: It works, and then it doesn't...connecting to a daemon over the net
by Thelonius (Priest) on Jun 12, 2003 at 20:43 UTC
    You have not given enough context to say what is happening. For example, you say "the 'run' button hangs". What does that mean? Is this a Tk application?

    The code: exec() unless fork() is not robust. If fork() fails, it returns undef. In this case your code is going to do an exec in the main process and not give an error. You really shouldn't try to write a one-liner here because there are three cases (1) parent (2) child (3) fork failed.

    One general-purpose debugging technique:

    # do this once (obviously, I hope) use IO::File; open LOG, ">>log.out" or die "opening log.out: $!\n"; LOG->autoflush(1); printf LOG "PROC $$: %d %s run starts %s\n", time, __FILE__, scalar(localtime); # put lots of these throughout your program printf LOG "PROC $$: %d %s(%d)\n", time, __FILE__, __LINE__;
    If you look at the times, you can see where your program is waiting. Scatter these liberally through your program. You may be surprised.
      It's an applet, the applet has a 'run' button, if I re-send a request before the first is finished, the java button doesnt 'de-click' until the first is finished and the second has started, thus it looks like it hangs.

      when you say 'through your program', do you mean the daemon, or the program the daemon is trying to run?

      S

      Dear Thelonius, After much messing around with your method of checking times, I've basically found where my daemon hangs and it still makes no sense whatsoever.

      basically, the daemon hangs right at the start of the request. My very first

      use IO::File; open LOG, ">>log.out" or die "opening log.out: $!\n"; LOG->autoflush(1); printf LOG "PROC $$: %d %s run starts %s\n", time, __FILE__, scalar(localtime);

      for the second request (remember, it is sent while the first program is running) does NOT APPEAR UNTIL THE FIRST REQUEST HAS FINISHED!!!!

      This means that activation of the very function, 'go' does not start until monster has finished running...does this make sense to anyone?

      it seems like the fork is not done completely or something, so though the 'return' happens easily after the first time, 'go' is still waiting for the fork to finish....

      any ideas?

      thanks

      Sam

Re: It works, and then it doesn't...connecting to a daemon over the net
by Thelonius (Priest) on Jun 12, 2003 at 21:56 UTC
    It's an applet, the applet has a 'run' button, if I re-send a request before the first is finished, the java button doesnt 'de-click' until the first is finished and the second has started, thus it looks like it hangs.

    when you say 'through your program', do you mean the daemon, or the program the daemon is trying to run?

    Well, I meant the Perl daemon, but you can use the technique in each program. It's not clear where the problem is. The more output, the better.

    I should have read your question more closely. Is the program "/usr/local/bin/monster" interacting with the XML-RPC client or does it just go off and do its own thing? If it never sends an XML-RPC response back, you may want to close STDIN, STDOUT and maybe other open files after you fork. You can do it in /usr/local/bin/monster but it would be better to do it before you exec(). (You can also set close-on-exec if you know how to do that.)

      If it never sends an XML-RPC response back, you may want to close STDIN, STDOUT and maybe other open files after you fork. You can do it in /usr/local/bin/monster but it would be better to do it before you exec(). (You can also set close-on-exec if you know how to do that.)

      Well, funnily enough the XML-RPC response occurs correctly. the applet doesn't specifically 'wait' for a response, but the XML-RPC class I'm using seems to want to wait anyway:

      if(mx.getRun()){ Vector params = new Vector(); params.add(mx.toString()); try{ client.execute("Monster.go", params); getAppletContext().showDocument(new URL("http://mo +nster.northwestern.edu/monster.jsp?pji="+id)); } catch(ConnectException ex){ex.printStackTrace();} catch(IOException ex){ex.printStackTrace();} catch(XmlRpcException ex){ ex.printStackTrace(); try{ getAppletContext().showDocument(new URL("http: +//monster.northwestern.edu/monster.jsp?pji="+id)); }catch(MalformedURLException exc){exc.printStackTr +ace();} } }
      i added the '.showDocument' in the XmlRpcException catch, because it threw if it got a return that was weird, so just knowing that a return happened tells me the 'exec' happened (i hope). adding that catch didnt change a thing about the button hanging.

      To answer your question:

      Is the program "/usr/local/bin/monster" interacting with the XML-RPC client or does it just go off and do its own thing?

      monster does its own thang, the 'return 0' in the daemon IS the final interaction with the XML-RPC client.

      i'll have a go at checking where the hanging happens in the daemon, cheers

      Sam

Re: It works, and then it doesn't...connecting to a daemon over the net
by Thelonius (Priest) on Jun 19, 2003 at 02:55 UTC
    basically, the daemon hangs right at the start of the request. My very first
    use IO::File; open LOG, ">>log.out" or die "opening log.out: $!\n"; LOG->autoflush(1); printf LOG "PROC $$: %d %s run starts %s\n", time, __FILE__, scalar(localtime);
    for the second request (remember, it is sent while the first program is running) does NOT APPEAR UNTIL THE FIRST REQUEST HAS FINISHED!!!!
    Have you tried closing STDOUT on the child process as I suggested above? The STDOUT of the child process is connected to the socket back to the applet. I think the applet is waiting for the socket to close. The second request doesn't even get sent from the applet until the child process finishes executing. If you close STDOUT, I think all will be fine.
Re: It works, and then it doesn't...connecting to a daemon over the net
by seaver (Pilgrim) on Jun 12, 2003 at 20:01 UTC
    Before I forget, the return value is absolutely necessary for the browser to know that the interaction with the daemon was successful.