MATLAB Answers

Patrik Ek
1

How to do workaround MATLAB crash in set(gcf,'C​urrentAxes​',ax1)?

Asked by Patrik Ek
on 5 Nov 2014
Latest activity Answered by Kelly Kearney
on 8 Dec 2014
Hi,
I have used matlab for a long time and always liked it. That to say until version 2014b. This version seems to have severe concurrency problems. I got this crash today:
Error using matlab.ui.Figure/set
Axes must be an existing child of figure.
Error in nrOfUEs (line 87)
set(gcf,'CurrentAxes',ax1);
Error in Throughput_stats (line 1071)
nrOfUEs(Stop, NrUE);
Error in femto_all_thrp (line 60)
Throughput_stats(...
87 set(gcf,'CurrentAxes',ax1);
But in debug mode right after this crash manually typing
K>> set(gcf,'CurrentAxes',ax1);
Does not give an error. There are a few possible causes to this problem, depending on what the error message really mean in matlab:
1) The handle is not created
This is however unlikely since the loop
while ~ishandle(ax1)
fprintf('waiting...\n');
end
is not triggered.
2) The handle is modified in row 79 and is thus locked with a mutex lock or other preferred lock
3) The axes are modified, and thus not accessible
There may (mostl likely) also be other possible issues with this. The question is
Are there any workarounds to this problem?
My relevant code row 78-87
78 % Link the x-axes (for zooming purpouse)
79 linkaxes([ax1 ax2], 'x');
81 % Set the original axes to be the current (in case you want to modify it or
82 % anythin)
83 while ~ishandle(ax1)
84 fprintf('waiting...\n');
85 end
87 set(gcf,'CurrentAxes',ax1);

  0 Comments

Sign in to comment.

3 Answers

Answer by Patrik Ek
on 5 Nov 2014
 Accepted Answer

I just found an answer to the problem, but I still wanted to publish this question to raise the problem. I would not be able to send a bug report to this problem since I would in that case have to submit company secrets. Also this would not come until earliest update 2015b.
The workaround I found was:
while ( ~any( get(gcf,'Children')==ax1 ) )
pause(1);
fprintf('waiting...\n'); % Not necessary, but this helps to see if the code enters the loop
end
This gives the other thread time to finish the GUI.
I would be happy for suggestions about title to reach a larger audiance.
Good Luck All!

  0 Comments

Sign in to comment.


Answer by Kelly Kearney
on 8 Dec 2014

I'm not sure if it's entirely related, but I have also found the need to throw a lot of drawnow commands into some of my code in order for it to be compatible with R2014b.
Same basic symptoms... a command that accesses the properties of a graphics object would return an error, but if I placed a breakpoint on that line, the error would not be reproduced. Adding a drawnow just before the command fixed the issue by forcing a mid-calculation render, but it's not an ideal solution (since in my case this results in intermediate-stage rendering, i.e. graphics objects that flash on and off as they're being repositioned, while older versions were able to do this repositioning behind the scenes).
When I submitted a bug report about this, they said this wasn't a bug but just a "timing issue". My takeaway was that at least for now, when programming for 2014b, never assume that a graphics-related line of code will be fully executed before the program moves on to the next graphics-related command, unless you explicitly force it with a drawnow.

  0 Comments

Sign in to comment.


Answer by Mike Garrity
on 5 Nov 2014

From the error message, my guess is that you've got multiple figures, and gcf isn't what you think it is.
Perhaps something more like this would be appropriate:
set(ancestor(ax1,'figure'),'CurrentAxes',ax1)
That's saying that you want ax1 to be the CurrentAxes of its figure, rather than saying that you want ax1 to be the CurrentAxes of whatever figure happens to be gcf at the moment.

  3 Comments

Well that could be one possibility, if this is what is causing the crash. However, matlab had been working on the same figure for some time, so that should not be the problem. Also waiting until the figure gets a child ax1 does indeed work. It feels kind of strange that the code keeps crashing at the same line but not for not in the same turn in the loop. It is also strange that not doing anything but waiting solves the problem.
I can also add that I am not the original author and that the code was written several years ago. This crash have never occurred before matlab 2014b though and then started to occur frequently. This makes me guess that it is a concurrency issue, but since matlab is supposed handle these issues, there are not enough tools or clear enough error messages to find out exactly what causes the crash.
I can however try to print the current figure for the cases where matlab enters the while loop. That would indeed be useful information so thanks for the suggestion. This may also cause a timeout error instead if the current figure is not the expected one. This would actually confirm the theory that you have.
No, that kind of assumption about which figure is gcf has never really been safe. You should always check which figure is current instead of assuming.
Consider the following example:
nfigs = 10;
figs = [];
pos = get(0,'DefaultFigurePosition');
for i=1:nfigs
figs = [figs, figure('Position',pos + i*[10 -10 0 0])];
end
for i=1:100000
f = figs(randi(nfigs,1));
figure(f);
pause(.1);
if gcf ~= f
disp wrong
end
end
While this is running, try clicking on different windows, or if you're on Windows, try using ALT-TAB. You'll see that in any version of MATLAB you'll occasionally see that "wrong" message. That's because the current figure can be set in more than one way. The MATLAB code that is calling figure can't safely make assumptions about what's happening on the other side, and that call to pause lets events in from the other side.
I think that it is true that this might happen more frequently in R2014b. That's because more of the graphics work has been moved off of the compute thread. But the possibility that gcf changed during the pause is not new.
The little code snippet I gave you will always set the CurrentAxes property on the correct figure, regardless of whether that changed during the pause, because the call to ancestor always returns the figure which ax1 belongs to, even if that's not gcf.
I am not sure if this s really the cause. What I know this requires some user interaction, what I did was actually that I started the program and not touching anything since I know that activating different figures can cause the current figure to change. The thing that were a bit disturbing was that using code that have been run for many years and that have never crashed so far suddenly crashed. What also was strange was that waiting until the handle existed worked.
To clarify. Without me touching the mouse, the keyboard, while running the given code on a newly restarted computer, got this error. What I had done was creating the figure in question, creating some plots in the figure and then in the end set ax1. It feels strange that the current figure should then not be the one that I required here. It is also strange that without further user interaction suddenly after less than 0.2 seconds (lowest time tested) suddenly getting the right figure as gcf. It feels as if something is fishy here, but I am not sure what.

Sign in to comment.