Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Non-blocking call to external program without losing return code

Tags:

matlab

When starting the external program (let's call it "EX" for brevity) from within Matlab I can either do it like this

[status, result] = system('EX.exe');

which blocks until EX returns, or like this

[status, result] = system('start EX.exe');

which returns to Matlab immediately but can't fetch EX's return code.

It would be nice to still have EX's return code available in Matlab once it is done. This would be the easiest way for the calling Matlab script to notice any problems EX might run into. On the other hand, I would like Matlab to do other stuff while EX is running, e.g. displaying information on progress. So, the call needs to be non-blocking.

I tried to work around this obvious conflict by starting EX as described in the first example above. To be able to run some other code (displaying progress information) while EX is busy, I put this code into a function and called that by using a timer with a small StartDelay.

Unfortunately this does not provide real multithreading (something that Matlab seems to be incapable of without Parallel Computing Toolbox), i.e. if the code in the timer callback runs longer than EX, execution again blocks until the timer callback returns. Even worse: Since I don't know how long EX will run, the timer callback must run endlessly until it is either stopped or passed some flag that tells it to stop. I tried with global variables or even storing this flag in application data like this:

setappdata(0, 'running', 1);

tim = timer(...
    'StartDelay', 2, ...
    'TimerFcn',   'while getappdata(0, ''running''), fprintf(''timer running ...\n''); pause(1); end' ...
);

fprintf('Starting timer.\n');
start(tim);

fprintf('Calling external program ...\n');
[s,r] = system('EX.exe');
fprintf('External program returned %d.\n', s); % <-- This is never reached.

setappdata(0, 'running', 0);

fprintf('Stopping timer.\n');
stop(tim);
delete(tim);

The code following the call to system() never seems to be executed and the timer callback runs forever ... Is there any other way I can get this to work or is it really either system's return value OR non-blocking call?

like image 838
Atze Kaputtnik Avatar asked Jul 15 '11 14:07

Atze Kaputtnik


2 Answers

I'm not sure MATLAB has native/built-in support for spawning a process. You can use Java from MATLAB to implement it, though.

For instance,

>> runtime = java.lang.Runtime.getRuntime();
>> process = runtime.exec('program arg1 arg2');
>> ...
>>
>>   % when you want to collect results.
>> process.waitFor(); % block until program returns.
>> process.exitValue(); % fetch process return code.
>>
>>   % or, if you need to abandon the work,
>> process.destroy(); % violently kill process
like image 170
André Caron Avatar answered Oct 14 '22 03:10

André Caron


If you have programmatic access to the other program, then the easiest way to get around this by far is to simply have the other program save results or progress notes to a textfile, and have matlab read that.

If you can't to do it that way, you may want to look into the parallel computing toolbox. You can use one thread to start the process and another thread to monitor it. I had a few questions myself on how to use the toolbox; try out their examples and post future questions here. Good luck!

like image 26
eykanal Avatar answered Oct 14 '22 02:10

eykanal