http://qs1969.pair.com?node_id=768159

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

I apoligize in advance, but company restrictions forbid me from posting any code. Even though I had to teach myself perl, I will try to make my request for wisdom as clear as possible.

I'm trying to write a script that calls 2 other perl scripts, then a MATLAB script followed by a 3rd perl script. I have no problem getting any of the programs to start and run correctly, but I can't seem to figure out how to make the last perl script wait until the MATLAB script is finished before it is called.

For error checking I decided to call MATLAB using system(), because I thought perl waits until the program is finished and assigns a value of 0 upon a succesful exit. What system seems to actually do is return 0 once MATLAB starts.

The goal is to automate these 4 tasks to run every night after my co-workers and I leave for the day. The MATLAB program and last perl script are very resource-intensive processes that take at least 4 hours each to complete. Because the present version of my script calls the last script before MATLAB is finished, both programs run at the same time and crash the system.

My question is, how can I force perl to wait until MATLAB is finished before calling the last program? I currently call MATLAB in background mode (the program does not load as a GUI like normal, and returns all results in a log file upon exit).

Replies are listed 'Best First'.
Re: Calling External Program
by almut (Canon) on Jun 03, 2009 at 21:06 UTC
    I currently call MATLAB in background mode...

    You'll probably have to consult the MATLAB documentation on how to run the program in a way that it doesn't return before having finished. Maybe running it in the background isn't the way to go... Can you run it in batch mode (i.e. without the GUI), but in the foreground?

    Or, if that's not possible, you could maybe let the MATLAB job create a certain file when done (acting as a "finished" flag), whose existence you could then poll from your Perl script.

Re: Calling External Program
by Perlbotics (Archbishop) on Jun 03, 2009 at 21:30 UTC

    You didn't tell us which platform you're on (Windows? Unix?). What does the system call return?

    Some Ideas (since you cannot post code, we can try to guess your approach / chose a number next time ;-):

    1. system("....matlab someargs &"); --- get rid of the &
    2. system("nohup ....matlab someargs &"); --- get rid of nohup and &
    3. system("....matlab someargs"); --- check if matlab is a script that in turn starts a background process
    4. system("....matlab someargs"); --- something special about someargs?
    5. ...
    Your Perl program could identify the MATLAB PID and wait (checking for the PID's existence periodically) until the process terminates before starting the next script.

    Update:
    Nothing to be sorry for. I'am not familiar enough with Windows and Matlab to give you any further suggestions... ok, maybe yet another: I found a tutorial that looks quite good. There, the batch mode is described (see section: Getting Started). There, the exit command is suggested to terminate batch-runs. So I assume, the batch mode has to be terminated explicitly. Maybe check your *.m files for any occurrences of exit that might terminate the script execution early and modify your command to matlab -sd Directory -r File1;File2;exit ... maybe that helps? You can even call Perl programs from Matlab (see here ; shell scripts also). So another workaround might be the creation of File3.m that just contains a perl() or system() call to start your 3rd script? Well, at least the true Matlab hackers have something to grin ;-)

      Sorry about that. I'm running on Windows XP.

      As for the system call, I can give you the dos command equivalent, which is
      matlab -sd Directory -nosplash -r File1;File2
      where Directory is the directory containing the files to run, -nosplash makes it run in background mode (I first tested it in GUI mode to make sure everything worked), and -r Files contains the files to be run. Perl behaves the same regardless of whether or not MATLAB is in background mode. I will try your suggestion to check for the PID periodically.
        I have done something similar - though not exactly the same - with Win32::Process::Create. That gives you a $ProcessObj->Wait($timeout) method. However, from your description, I suspect that this will return immediately.

        If Wait() does return immediately, you should be able to find an entry in the tasklist for what is running and check that periodically for the programs completion. Without being more familiar with MATLAB, I can't be any more specific.

Re: Calling External Program
by bichonfrise74 (Vicar) on Jun 03, 2009 at 22:26 UTC
    I agree with Perlbotics that your Perl program should just look for the PID of Mathlab and wait for it to finish. Or you can do something like

    ps aux | grep <mathlab process>

    and wait for this process to finish.
Re: Calling External Program
by sgifford (Prior) on Jun 04, 2009 at 02:03 UTC
    Or, if it writes something in the log that indicates it has finished, monitor the log file to see when that something appears. If it writes its PID in the log file, even better: get the PID from there, then waitpid for it.