views:

210

answers:

5

Problem: scriptA.cgi is sitting in an infinite loop and handling an open socket to a Flash client. scriptB.cgi is called from the web, does what it needs to do and then needs to inform scriptA to send a message to the client.

Is this possible? I'm stuck on how to have scriptB identify the instance of scriptA that is sitting there with the socket connection, rather than launching one of its own.

all thoughts appreciated.

+5  A: 

If the communication needs are simple, this is a good application for signals.

Edited to store process id from scriptA and read it in scriptB -- scripts A and B have to agree on a name.

 # script B
 do_scriptB_job();
 if (open(my $PID_FILE, "<", "scriptA.pid.file")) {
   $process_id_for_scriptA = <$PID_FILE>;
   close $PID_FILE;
   kill 'USR1', $process_id_for_scriptA;  # makes scriptA run the SIGUSR1 handler
 }


 # script A
 open(my $PID_FILE, ">", "scriptA.pid.file");
 print $PID_FILE $$;
 close $PID_FILE;
 my $signaled = 0;
 $SIG{"USR1"} = \sub { $signaled = 1 } # simple SIGUSR1 handler, set a variable
 while ( in_infinite_loop ) {
     if ($signaled) {
         # this block runs only if SIGUSR1 was received 
         # since last time this block was run
         send_a_message_to_the_client();
         $signaled = 0;
     } else {
         do_something_else();
     }
 }
 unlink "scriptA.pid.file";   # cleanup

When script A receives a SIGUSR1 signal, the script will be interrupted to run the USR1 signal handler, setting $signaled. The thread of execution will then resume and the script can use the information.

mobrule
You did not address this bit: *I'm stuck on how to have scriptB identify the instance of scriptA that is sitting there with the socket connection*
Nifle
yeah... that's actually the part I'm lost on... once I have that, I can figure out the rest.
Dr.Dredel
+1 after edit .
Nifle
using signals as above really only works if the cgi scripts are viewed by only one browser.
IanNorton
A: 

Domain sockets: http://www.perl.com/doc/FMTEYEWTK/IPC/unix.html ?

Xepoch
+2  A: 

Have scriptA store it's pid somwhere (in a db with some kind of id), then scriptB can look up the pid in the db and send a signal to scriptA.

Edit:
Answering question asked in comment

The pid of the process can be found using perls builtin variables $$ or $PID or $PROCESS_ID depending on how old your perl is.

See perlvar for details.

I hope this is the ID you where looking for. If not you'll have to find a way to separate the different scriptA instances. (Perhaps by session id, or socket. Here I cant help you further)

Nifle
how does scriptA get its ID?
Dr.Dredel
Edited answer to provide more info.
Nifle
+2  A: 

Other people have mentioned how to get the PID (if you didn't fork() it yourself, just have the other-process write it... somewhere... that both processes know how to get it. or walk the process table, but that's a horrible solution and completely unscalable beyond a singleton).

Since you note that any thoughts are welcome, note that perldoc perlipc explains a variety of mechanisms you might use for the actual communication:

NAME
    perlipc - Perl interprocess communication (signals, fifos, pipes, safe
    subprocesses, sockets, and semaphores)

DESCRIPTION
    The basic IPC facilities of Perl are built out of the good old Unix
    signals, named pipes, pipe opens, the Berkeley socket routines, and SysV
    IPC calls. Each is used in slightly different situations.
fennec
that is indeed very useful. thanks (and welcome to SO) :)
Dr.Dredel
A: 

I was tempted to answer, 'send signals' or 'use some kind of IPC to talk between apps' but, a far easier and scalable approach is to use a sqlite (or other) database that all scripts can talk to,

ScriptA.cgi would poll the database by doing something like 'SELECT event FROM events WHERE clientID=?'.

ScriptB.cgi would simply insert a row into the events table with the right clientID.

That avoids all of the 'find the pid' mess and also mean that you don't get the blocking IO problems you would get with named pipes or if one script crashed.

IanNorton
I already have a DB in the mix, but I'm not certain this approach is ideal because then the process that is being signaled will need to pound the db every 100 milliseconds looking for a cue to do whatever it's supposed to do.
Dr.Dredel