21

I would like to be able to terminate my current running scripts( functions ) by calling a command in the code. Return would only terminate the current function not entire script. Therefore return is not the one.

What I am looking for is a command which does exactly what CTRL + C do. I have already seen this: how to stop execution and noticed that no one has yet provided a proper answer for this question in there either.

ultimately I want to terminate the entire running scripts upon closing a figure:

hFig = figure('CloseRequestFcn',{@closeHandler});

.
.
.
function closeHandler (src,evnt)

    CTRL+C    <--- I am looking for such a command     
end

PS. function error() will not work either: Try this:

function terminateInCode()

hFig = figure('CloseRequestFcn',{@closeHandler});

while(1)

   plot(10*rand,10*rand,'+');
   pause(0.1);
end;

   function closeHandler (src,evnt)
      delete(hFig);
      error('program terminated!');
   end
end
BenMorel
  • 34,448
  • 50
  • 182
  • 322
C graphics
  • 7,308
  • 19
  • 83
  • 134
  • 1
    It would help if you could explain the reason why you want this behavior. This is undocumented/unsupported/undoable within matlab at present, so why do you want to do it? What problem is driving you to this unworkable solution? – John Apr 17 '12 at 21:06
  • I wanna terminate the entire running script upon closing a figure. – C graphics Apr 18 '12 at 18:47

7 Answers7

14

Here is a sample function with example based on yuk's answer. Components include:

  • Insure the command window has focus to receive the CTRL+C
  • Use a timer to release CTRL+C after the break has occurred
  • Use a Java robot to press CTRL+C

Sample function is below:

function terminateExecution
%terminateExecution  Emulates CTRL-C
%    terminateExecution   Stops operation of a program by emulating a
%    CTRL-C press by the user.
%
%    Running this function
%
%Example:
%for ix = 1:100
%    disp(ix)
%    if ix>20
%        terminateExecution;
%    end
%end

%1) request focus be transferred to the command window
%   (H/T http://undocumentedmatlab.com/blog/changing-matlab-command-window-colors/)
cmdWindow = com.mathworks.mde.cmdwin.CmdWin.getInstance();
cmdWindow.grabFocus();

%2) Wait for focus transfer to complete (up to 2 seconds)
focustransferTimer = tic;
while ~cmdWindow.isFocusOwner
    pause(0.1);  %Pause some small interval
    if (toc(focustransferTimer) > 2)
        error('Error transferring focus for CTRL+C press.')
    end
end

%3) Use Java robot to execute a CTRL+C in the (now focused) command window.

%3.1)  Setup a timer to relase CTRL + C in 1 second
%  Try to reuse an existing timer if possible (this would be a holdover
%  from a previous execution)
t_all = timerfindall;
releaseTimer = [];
ix_timer = 1;
while isempty(releaseTimer) && (ix_timer<= length(t_all))
    if isequal(t_all(ix_timer).TimerFcn, @releaseCtrl_C)
        releaseTimer = t_all(ix_timer);
    end
    ix_timer = ix_timer+1;
end
if isempty(releaseTimer)
    releaseTimer = timer;
    releaseTimer.TimerFcn = @releaseCtrl_C;
end
releaseTimer.StartDelay = 1;
start(releaseTimer);

%3.2)  Press press CTRL+C
pressCtrl_C

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function pressCtrl_C
    import java.awt.Robot;
    import java.awt.event.*;
    SimKey=Robot;
    SimKey.keyPress(KeyEvent.VK_CONTROL);
    SimKey.keyPress(KeyEvent.VK_C);

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function releaseCtrl_C(ignore1, ignore2)
    import java.awt.Robot;
    import java.awt.event.*;
    SimKey=Robot;
    SimKey.keyRelease(KeyEvent.VK_CONTROL);
    SimKey.keyRelease(KeyEvent.VK_C);
Community
  • 1
  • 1
Pursuit
  • 12,285
  • 1
  • 25
  • 41
  • I suggest you upload this to the file exchange. Let me know when you do, so that I can use the properly attributed file. – Jonas Apr 15 '12 at 02:23
  • the code doesn't work with nested loops (matlab 2011a) - check this code: `for j = 1 : 10 for k = 1 : 10 if j > 2 && k > 2 terminateExecution; disp(['j = ' num2str(j)]); disp(['k = ' num2str(k)]); end end end` – memyself Apr 17 '12 at 10:43
  • @memyself: The function actually works even in your example. It just that the response requires some time and it seems 100 loops is not enough. Try 100 for both `j` and `k`. In my case it terminated the code at `j=19` and `k=33`. – yuk Apr 17 '12 at 16:15
  • @yuk I assume that C graphics is looking for a general solution and not only one which works if j & k are > 100. – memyself Apr 17 '12 at 16:17
  • @memyself: My point is you need to increase the number of loops to show that the function works. The question was to reproduce Ctrl+C behavior. And Ctrl+C does not work immediately as well. – yuk Apr 17 '12 at 16:22
  • Adding `drawnow` (twice?) or some sort of pause seems to fix some of the timing issues. But I'm still getting the control key stuck occasionally (on Mac). – mbauman Apr 17 '12 at 16:44
  • 2
    It looks like function initially posted only works if the command window has focus. Otherwise the CTRL+C is sent to a window where it does not stop execution, see edit for fix. The "keyRelease" functions do not always execute, so I also sometimes get the CTRL key stuck on. Not sure of a fix for that yet. – Pursuit Apr 17 '12 at 17:01
  • New edit takes care of key release. I believe that of the java Robot works at all on a machine (not guaranteed), this this will work. Comments on why the Robot may not work on a particular configuration are here: http://docs.oracle.com/javase/6/docs/api/ – Pursuit Apr 17 '12 at 21:45
  • 2
    @Persuit - nice work! See my alternative for something a bit simpler that circumvents all these problems... but it does so by way of a protected method. :) – mbauman Apr 17 '12 at 21:49
7

Not sure it will work, just an idea. How about to emulate keyboard key press from MATLAB?

You can try either java.awd.Robot:

import java.awt.Robot;
import java.awt.event.*;
SimKey=Robot;
SimKey.keyPress(KeyEvent.VK_CONTROL);
SimKey.keyPress(KeyEvent.VK_C);

or WScript.Shell and SendKeys.

yuk
  • 19,098
  • 13
  • 68
  • 99
  • -1. This sticks the control and c keys down without recourse on my Mac, and doesn't work on my Windows machine (R2011a for both). If the bounty defaults, I'd rather see it go toward @Persuit's modification and flushing out of this idea. – mbauman Apr 17 '12 at 21:14
  • @MattB.: First of I don't expect the bounty just for an idea. I believe OP can assign bounty to any answer what he likes the most and I hope he will do it rather than leaving it to default. Don't see your reason for downvote. BTW I did upvoted the Persuit's answer. – yuk Apr 18 '12 at 15:41
  • It's a great idea. :) But it's incomplete and buggy. Please don't take the downvote personally; I left three reasons in the comment. My understanding of the bounty system is that if the offerer doesn't allocate it, it defaults to the highest upvoted answer. That may be incorrect (?), but my point about the keys getting stuck on the Mac stands. Quite simply - I think that the voted order of the answers should be different than the status quo. Persuit's answer is more complete than yours. Downvoting helps accomplish this. If my understanding of the etiquette here is wrong, please forgive me. – mbauman Apr 18 '12 at 17:23
6

Unfortunately, it seems it cannot be done:

Mathworks

There is no way to programmatically issue a Ctrl+C in MATLAB besides using the keyboard's Ctrl+C combination.

As an alternative, you can use the ERROR command to force an error that will exit the code. For example:

error('Program terminated for a specific reason')
Community
  • 1
  • 1
Smash
  • 3,722
  • 4
  • 34
  • 54
4

Here's an alternative that uses undocumented Matlab calls to place the key event directly into the command window. The method to do so is protected; this uses reflection to unprotect it.

Unlike @yuk and @Persuit's answers, this does not seem to have issues with the control key sticking. Additionally, it will always post directly to the command window without any race conditions or other issues of ensuring focus. And, I think that it fires deterministically -- it'll execute immediately.

The one caveat is that it uses an undocumented call to retreive the handle of the command window instance. This varies slightly by release as it is dependent upon the window frame layout. Some of Yair Altman's (undocumentedmatlab.com) work on the file exchange has more robust functions to grab this in a more general fashion; this code should work with most modern releases of Matlab (Tested on R2011a, both Mac & Win).

function interrupt

import java.awt.event.KeyEvent
import java.util.Calendar
import java.lang.reflection.*

cmdwin = handle(com.mathworks.mde.cmdwin.CmdWin.getInstance().getComponent(0).getComponent(0).getComponent(0),'CallbackProperties');

argSig = javaArray('java.lang.Class',1);
argSig(1) = java.lang.Class.forName('java.awt.event.KeyEvent');
method = cmdwin.getClass().getDeclaredMethod('processKeyEvent',argSig);
method.setAccessible(true);

cal = Calendar.getInstance();
args = javaArray('java.lang.Object',1);
args(1) = KeyEvent(cmdwin,KeyEvent.KEY_PRESSED,cal.getTime().getTime(),KeyEvent.CTRL_DOWN_MASK,KeyEvent.VK_C,KeyEvent.CHAR_UNDEFINED);
method.invoke(cmdwin,args);
mbauman
  • 30,958
  • 4
  • 88
  • 123
  • It is how it is supposed to be invoked?function tempFigure() hFig = figure('CloseRequestFcn',{@closeHandler}); while(1) plot(10*rand,10*rand,'+'); pause(0.1); end; function closeHandler (src,evnt) delete(hFig); interrupt; end end – C graphics Apr 18 '12 at 18:38
  • It closes the script but apparently does not bring the command prompt back( in command Window), or perhaps I am not using it the right way ha? – C graphics Apr 18 '12 at 18:44
  • 1
    Oh, interesting. Yes, you're calling it correctly, but since it's being executed inside a close function it's the close function that errors and gets aborted. This is a race condition that intrinsically exists within Matlab but rarely occurs (try manually typing ctrl-c during a pause within the close fcn). As such, the slight delays from the robot actually help you in this case. – mbauman Apr 18 '12 at 19:13
  • Thank you! From my experience that seems to be much more robust than the version suggested by @pursuit. – nirvana-msu Aug 16 '16 at 13:52
  • Great tool! I had to replace one line to avoid a warning: cmdwin = handle(com.mathworks.mde.cmdwin.CmdWin.getInstance(1).getComponent(0).getComponent(0).getComponent(0),'CallbackProperties'); – Massimo Oct 16 '22 at 14:04
  • The warning message otherwise is: Warning: A value of class "com.mathworks.mde.cmdwin.CmdWin" was indexed with no subscripts specified. Currently the result of this operation is the indexed value itself, but in a future release, it will be an error. – Massimo Oct 16 '22 at 14:37
2

You can use the function error. You will go back to matlab.

It will produce an error, but that is also what usually happen when you press CTRL+C, in a matlab script.

You should add some kind of message like error('Interrupted by user');

Oli
  • 15,935
  • 7
  • 50
  • 66
1

It is not exactly what you are asking for, but considering your example, your problem can be solved like that:

function terminateInCode()

hFig = figure('CloseRequestFcn',{@closeHandler});

stop=0;
while(~stop)
   plot(10*rand,10*rand,'+');
   pause(0.1);
end;

   function closeHandler (src,evnt)
      delete(hFig);
      stop=1;
   end
end
Oli
  • 15,935
  • 7
  • 50
  • 66
-2

Try the return statement. It will push you out of a function.

If you want to terminate it completely you need to use ERROR.

You could always use EXIT if its really that disastrous.

Adam Hess
  • 1,396
  • 1
  • 13
  • 28