Matlab onCleanup function not executed - matlab

I ran into the following issue in MATLAB R2013a, which for some reason I do not understand does not call the onCleanup function when in a function a timer (including a TimerFcn) is defined.
I add two minimal examples showing the problem:
first the working version where the cleanup routine is called as expected:
function mytest(time)
t = timer();
myclean = onCleanup(#() disp('function ended'));
pause(time);
end
and now the buggy version in which the cleanup is not called (neither when the function ends normally or when ctrl+c is pressed)
function mytest2(time)
t = timer();
t.TimerFcn = #(o,s)disp(' ... waiting for some time');
myclean = onCleanup(#() disp('function ends'));
pause(time);
end
I could not find any hints in documentation why the timer or more specific the definition of the TimerFcn would change the execution of the cleanup code?

Ouch - this is nasty. It's not a bug, but it's certainly not what you'd expect from the documentation, and it's not what you'd want. Fortunately it's pretty easy to work around.
Firstly, what's happening?
Well, onCleanup returns you an onCleanup object. This is an object whose sole purpose is to have a destructor method that is set to your #() disp('function ends'). When the object goes out of scope (which you would expect to be at the end of the function mytest2), it gets deleted, its destructor method executes, and your message gets displayed. That's what you expect, I think.
But when you create the anonymous function #(o,s)disp(' ... waiting for some time'), and assign it to the TimerFcn of your timer, it takes a copy of the entire current workspace of the function mytest2, including the onCleanup object. The timer is created in the base workspace (not the function workspace), and remains in existence even at the end of the function, along with the onCleanup object, which then never goes out of scope, never gets deleted, its destructor function never runs, and you don't get your message.
Note that:
If you run a = timerfindall; delete(a); in the base workspace, you will get your message, as you've explicitly deleted the timer along with the onCleanup object.
This behaviour about anonymous functions taking a copy of their entire workspace is fully documented, although you may not be aware of it, and although you clearly don't want it to work like that here. It's nasty.
Fortunately, it's easy to work around:
function mytest3(time)
t = timer();
setTimerFcn(t)
myclean = onCleanup(#() disp('function ends'));
pause(time);
end
function setTimerFcn(t)
t.TimerFcn = #(o,s)disp(' ... waiting for some time');
end
Now, when the anonymous function is created it only takes a copy of its local workspace (i.e. from the subfunction setTimerFcn), which does not include the onCleanup object. The onCleanup object goes out of scope at the point you expect it to, and everything's fine.
Hope that helps!

a possible workaround (found by a colleague of me) is to move to definition of the timer into a own function. It is not clear to us why this works but it seems that the definition of a timer in matlab changes the context of some local variables of the function which are not 'deleted' after the function ends as it would be expected from the matlab documentation (Object Life cycle of variables in Matlab)
A working example is shown below (it uses the defined timer to print simple status messages while waiting) and upon Ctrl+c or when the function ends the Timer is stopped. It furthermore makes sure that only one timer with the name 'timer-mywait' is defined.
function mytest3(time)
% register Cleanup handler
c = onCleanup(#()onCleanup_fcn);
t = mywait_timer(time);
wait(t);
% onCleanup handle function
function onCleanup_fcn
tm = timerfind('Name','timer-mywait');
if ~isempty(tm) && any(strcmpi(get(tm,'running'),'on'))
disp('Stopped running timer ''timer-mywait''!');
stop(tm);
end
end % onCleanup_fcn
end %mytest3
function t = mywait_timer(time)
N = 5;
t = timerfind('Name','timer-mywait');
if isempty(t) % avoid multiple definitions of the same timer
t = timer();
end
t.ExecutionMode = 'fixedRate';
t.TasksToExecute = N+1;
t.Period = str2num(sprintf('%.3f',time/N)); % Matlab complains about more digits!
t.Name = 'timer-mywait';
t.TimerFcn = #(o,s)mywait_timercb();
start(t),
end % mywait_timer
function mywait_timercb()
disp(' still waiting ... ');
end % mywait_timercb

Related

fatalAssertNotError-like-method in MATLAB unit test

I am writing a class-based test suite in MATLAB for a timeseries handling package. The first test in my suite needs to check whether a connection exists to a Haver database on a network drive. If the connection does not exist, then the first test should abort the rest of the suite using one of the fatalAssert methods.
One complicating factor, which I have excluded from the exposition below, but I will mention now is that I need to use an anonymous function to check the connection to Haver (unless someone has a better idea). My package handles data from multiple sources, Haver only being one of them.
I have a parent-class test suite that performs general tests for all of the sources. I then inherit this parent-class into specific child-class test suites and set specific parameters in their respective TestMethodSetup method. One of these parameters is an anonymous function, connfun, and a location, connloc, which I use in the parent-class to test the connection. The reason I do this is because the parent tests are executed first, so I would have to wait for all of those to end if I wanted to test the connection in the child class.
This also complicates the order of execution. If I want to assign the connfun in the child class, then I have to use either the TestMethodSetup or TestClassSetup of the child class (open to recommendations on which is best here) and put this connection test in the Test method of the parent class. I noticed the if I put checkConn in the TestMethodSetup and TestClassSetup of the parent class was running before that of the child class, I was unable to pass the anonymous function and the test would be incomplete.
Putting the previous point aside for a moment, this was my first attempt at writing the test in the parent-class (note that I used a fatalAssertEqual instead of a fatalAssertTrue because isconnection() does not return a logical):
methods (Test)
function checkConn(testCase)
connloc = 'pathToHaverDatabase';
connfun = #(x) isconnection(haver(x));
testCase.fatalAssertEqual(connfun(connloc), 1);
end
end
The above works when there is a connection, but the problem that I bumped into with this is that when I cannot access connloc, an error ocurrs during the call to haver(). So instead of returning a 1 or 0 from the isconnection() call that I can fatalAssertEqual on, all of checkConn errors out due to haver(). This then leads to the rest of the tests running (and failing, which is exactly what I want to avoid).
My next idea works for both cases, but it feels like bad code, and does not have the anonymous function specification described above.
methods (Test)
function checkConn(testCase)
connloc = 'pathToHaverDatabase';
connfun = #(x) isconnection(haver(x));
try
isconn = connfun(connloc);
catch
isconn = 0;
end
testCase.fatalAssertEqual(isconn, 1)
end
end
When I wrote this, I did not necessarily want to distinguish between not having access to the network drive, not being able to call the haver() function, and getting an isconnection equal to 0 because the last case covers all three. But I realized that if I did differentiate them, then it would be a bit more robust, but it's still missing the anonymous function taht I could pass from child to parent.
properties
connloc = 'pathToHaverDatabase';
end
methods (Test)
function checkDrive(testCase)
isfound = fillattrib(testCase.connloc);
testCase.fatalAssertTrue(isfound);
end
function checkHaver(testCase)
try
hav = haver(testCase.connloc);
ishaver = ~isempty(hav);
catch
ishaver = false;
end
testCase.fatalAssertTrue(ishaver);
end
function checkConn(testCase)
connfun = #(x) isconnection(haver(x));
testCase.fatalAssertEqual(connfun(testCase.connloc), 1);
end
end
Ideally, what I would want is a fatalAssert method (or something similar) that ends the test suite when its input is an error. Something that would perhaps be called fatalAssertNotError, but I don't think that exists. If it did, the last line of my first function would simply be testCase.fatalAssertNotError(connfun(connloc)) and I would not have to worry about all the cases.
I'm very open to dynamic rewrite of this whole test setup, so any specific comments or general advice are welcome!
First of all, I think the fatalAssert case is a strong use case to provide something like fatalAssertNotError. One reason why it is not part of the package is because many/most times people don't want to check whether something doesn't error, they just want to call the code, and if it errors, it fails for the test author automatically and it is much simpler. However, other qualification types like fatal assertions and assumptions perhaps point to the need to provide this so you can choose the outcome of the test in the presence of an error, in cases where you don't want it to fail (like with assumptions) or you want it to fail "more strongly" like with fatal assertions.
That being said, I am still not convinced that you can't achieve what you are ultimately trying to do without it. The question I have centers around why you can't use TestClassSetup. It is not clear to me exactly why you weren't able to customize in the derived test class to get the behavior you want. For example, does something like this work?
classdef BaseTest < matlab.unittest.TestCase
properties(Abstract)
connloc
connfun
end
methods(TestClassSetup)
function validateConnection(testCase)
% If this errors it behaves like an assertion (not fatal assertion)
% and fails all tests in the test class. If it doesn't error but
% doesn't return 1 then the assertion failure will occur.
testCase.assertEqual(connfun(connloc), 1,
'Could not establish a connection to the database');
end
end
end
classdef DerivedTest < BaseTest
properties
connloc = 'pathToHaverDatabase';
connfun = #(x) isconnection(haver(x));
end
methods(Test)
function testSomething(testCase)
% Have at least one test method to test it out
end
end
end
Hope that helps!
If you really want to use a function you can define a nested one like this:
methods (Test)
function checkConn(testCase)
connloc = 'pathToHaverDatabase';
function res = connfun(x)
try
res = isconnection(haver(x));
catch
res = false
end
end
testCase.fatalAssertEqual(connfun(connloc), 1);
end
end
Nested functions can be a bit confusing to me because of the way they share data with the parent function. There really is no difference between an anonymous function and a nested function.
The alternative is to put the function at the end of the file, outside the classdef block:
classdef ...
%...
methods (Test)
function checkConn(testCase)
connloc = 'pathToHaverDatabase';
function res = connfun(x)
try
res = isconnection(haver(x));
catch
res = false
end
end
testCase.fatalAssertEqual(connfun(connloc), 1);
end
end
%...
end
function res = connfun(x)
try
res = isconnection(haver(x));
catch
res = false
end
end
But I honestly don't understand why you need to have a function call within fatalAssertEqual. The code you have seems perfectly fine to me.

Clear persistent variables in local functions from within the main function

I have a code which consists of a single file containing multiple functions, some of which use persistent variables. In order for it to work correctly, persistent variables must be empty.
There are documented ways to clear persistent variables in a multi-function file, such as:
clear functionName % least destructive
clear functions % more destructive
clear all % most destructive
Unfortunately, I cannot guarantee that the user remembers to clear the persistent variables before calling the function, so I'm exploring ways to perform the clearing operation at the beginning of the code. To illustrate the problem, consider the following example:
function clearPersistent(methodId)
if ~nargin, methodId = 0; end
switch methodId
case 0
% do nothing
case 1
clear(mfilename);
case 2
eval(sprintf('clear %s', mfilename));
case 3
clear functions;
case 4
clear all;
end
subfunction();
subfunction();
end
function [] = subfunction()
persistent val
if isempty(val)
disp("val is empty");
val = 123;
else
disp("val is not empty");
end
end
When first running this, we get:
>> clearPersistent
val is empty
val is not empty
I would expect that running the function again at this point, with any of the non-0 inputs would result in the val variable being cleared, but alas - this is not the case. After val is set, unless we use one of the alternatives shown in the top snippet externally, or modify the .m file, it remains set.
My question: Is it possible to clear persistent variable in subfunctions from within the body of the main function, and if yes - how?
In other words, I'm looking for some code that I can put in clearPersistent before calling the subfunctions, such that the output is consistently:
val is empty
val is not empty
P.S.
Here's a related past question (which doesn't deal with this specific use case): List/view/clear persistent variables in Matlab.
I'm aware of the possibility of rewriting the code to not use persistent variables at all (e.g. by passing data around, using appdata, adding a 'clear' flag to all subfunctions, etc.).
Please note that editing the source code of the function and saving implicitly clears it (along with all persistent variables).
I'm aware that the documentation states that "The clear function does not clear persistent variables in local or nested functions.
Additional background on the problem:
The structure of the actual code is as follows:
Main function (called once)
└ Global optimization solver (called once)
└ Objective function (called an unknown N≫1 times)
└ 1st function that uses persistents
└ 2nd function that uses persistents
As mentioned in the comments, there are several reasons why some variables were made persistent:
Loose coupling / SoC: The objective function does not need to be aware of how the subfunctions work.
Encapsulation: It is an implementation detail. The persistent variables do not need to exist outside the scope of the function that uses them (i.e. nobody else ever needs them).
Performance: The persistent variables contain matrices that are fairly expensive to compute, but this operation needs to happen only once per invocation of the main function.
One (side?) effect of using persistent variables is making the entire code stateful (with two states: before and after the expensive computations). The original issue stems from the fact that the state was not being correctly reset between invocations of the main function, causing runs to rely on a state created with previous (and thus invalid) configurations.
It is possible to avoid being stateful by computing the one-time values in the main function (which currently only parses user-supplied configurations, calls the solver, and finally stores/displays outputs), then passing them alongside the user configurations into the objective function, which would then pass them on to the subfunctions. This approach solves the state-clearing problem, but hurts encapsulation and increases coupling, which in turn might hurt maintainability.
Unfortunately, the objective function has no flag that says 'init' etc., so we don't know if it's called for the 1st or the nth time, without keeping track of this ourselves (AKA state).
The ideal solution would have several properties:
Compute expensive quantities once.
Be stateless.
Not pass irrelevant data around (i.e. "need to know basis"; individual function workspaces only contain the data they need).
clear fname and clear functions removes the M-file from memory. The next time you run the function, it is read from disk again, parsed and compiled into bytecode. Thus, you slow down the next execution of the function.
Clearing a function or sub-function from within a function thus does not work. You're running the function, you cannot clear its file from memory.
My solution would be to add an option to subfunction to clear its persistent variable, like so:
function clearPersistent()
subfunction('clear');
subfunction();
subfunction();
end
function [] = subfunction(option)
persistent val
if nargin>0 && ischar(option) && strcmp(option,'clear')
val = [];
return
end
if isempty(val)
disp("val is empty");
val = 123;
else
disp("val is not empty");
end
end
Of course you could initialize your value when called as subfunction('init') instead.
A different solution that might work for your usecase is to separate the computation of val and its use. I would find this easier to read than any of the other solutions, and would be more performant too.
function main()
val = computeval();
subfunction(val);
subfunction(val);
end
Given your edit, you could put the objective function in a separate file (in the private subdirectory). You will be able to clear it.
An alternative to persistent variables would be to create a user class with a constructor that computed the expensive state, and another method to compute the objective function. This could also be a classdef file in the private subdirectory. I think this is nicer because you won’t need to remember to call clear.
In both these cases you don’t have a single file containing all the code any more. I think you need to give up on one of those two ideals: either break data encapsulation or split the code across two files (code encapsulation?).
Why not using global variables?
You can create a global struct that contains your variables and it can be managed using a variable_manager:
function main
variable_manager('init')
subfunction1()
subfunction2()
end
function variable_manager(action)
global globals
switch action
case 'init'
globals = struct('val',[],'foo',[]);
case 'clear'
globals = structfun(#(x)[],globals,'UniformOutput', false);
% case ....
% ...
end
end
function subfunction1
global globals
if isempty(globals.val)
disp("val is empty");
globals.val = 123;
else
disp("val is not empty");
end
end
function subfunction2
global globals
if isempty(globals.foo)
disp("foo is empty");
globals.foo = 321;
else
disp("foo is not empty");
end
end
As mentioned in the question, one of the possibilities is using appdata, which is not too different from global (at least when associating them with "object 0" - which is the MATLAB instance itself). To avoid "collisions" with other scripts/functions/etc. we introduce a random string (if we generate a string in every function that uses this storage technique, it would almost certainly guarantee no collisions). The main downside of this approach is that the string has to be hard-coded in multiple places, or the structure of the code should be changed such that the functions that use this appdata are nested within the function that defines it.
The two ways to write this are:
function clearPersistent()
% Initialization - clear the first time:
clearAppData();
% "Business logic"
subfunction();
subfunction();
% Clear again, just to be sure:
clearAppData();
end % clearPersistent
function [] = subfunction()
APPDATA_NAME = "pZGKmHt6HzkkakvdfLV8"; % Some random string, to avoid "global collisions"
val = getappdata(0, APPDATA_NAME);
if isempty(val)
disp("val is empty");
val = 123;
setappdata(0, APPDATA_NAME, val);
else
disp("val is not empty");
end
end % subfunction
function [] = clearAppData()
APPDATA_NAME = "pZGKmHt6HzkkakvdfLV8";
if isappdata(0, APPDATA_NAME)
rmappdata(0, APPDATA_NAME);
end
end % clearAppData
and:
function clearPersistent()
APPDATA_NAME = "pZGKmHt6HzkkakvdfLV8";
% Initialization - clear the first time:
clearAppData();
% "Business logic"
subfunction();
subfunction();
% Clear again, just to be sure:
clearAppData();
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function [] = subfunction()
val = getappdata(0, APPDATA_NAME);
if isempty(val)
disp("val is empty");
val = 123;
setappdata(0, APPDATA_NAME, val);
else
disp("val is not empty");
end
end % subfunction
function [] = clearAppData()
if isappdata(0, APPDATA_NAME)
rmappdata(0, APPDATA_NAME);
end
end % clearAppData
end % clearPersistent

Force return from function while debugging

I am debugging a program in MATLAB R2016a and would like to return from a sub-function without completing the function. For example, you can write in code:
if(conditionMet)
return;
end
If the condition is met, it will force the function to end early and continue in the caller code. While I am debugging, I would like to force the function to end early as if I had encountered a return command. When I simply type return while in debug mode, nothing appears to happens. Is there a way to force a function to end early and continue running?
According to MATLAB Central and Undocumented Matlab, there is an undocumented function feature() that could be used in your case like this:
if feature('IsDebugMode')
return;
end
I think it is not possible in general with the current release of Matlab.
If you know at beforehand at which place(s) you potentially want to return from your function while debugging, you can use the following trick.
function yourFunction ()
breakDebug = false;
...
if breakDebug
return; % location at which you may break your function during debugging
end
...
return;
end
By setting breakDebug while debugging, the program will break at your next potentially break location.

timer exit does not call onCleanup? [duplicate]

I ran into the following issue in MATLAB R2013a, which for some reason I do not understand does not call the onCleanup function when in a function a timer (including a TimerFcn) is defined.
I add two minimal examples showing the problem:
first the working version where the cleanup routine is called as expected:
function mytest(time)
t = timer();
myclean = onCleanup(#() disp('function ended'));
pause(time);
end
and now the buggy version in which the cleanup is not called (neither when the function ends normally or when ctrl+c is pressed)
function mytest2(time)
t = timer();
t.TimerFcn = #(o,s)disp(' ... waiting for some time');
myclean = onCleanup(#() disp('function ends'));
pause(time);
end
I could not find any hints in documentation why the timer or more specific the definition of the TimerFcn would change the execution of the cleanup code?
Ouch - this is nasty. It's not a bug, but it's certainly not what you'd expect from the documentation, and it's not what you'd want. Fortunately it's pretty easy to work around.
Firstly, what's happening?
Well, onCleanup returns you an onCleanup object. This is an object whose sole purpose is to have a destructor method that is set to your #() disp('function ends'). When the object goes out of scope (which you would expect to be at the end of the function mytest2), it gets deleted, its destructor method executes, and your message gets displayed. That's what you expect, I think.
But when you create the anonymous function #(o,s)disp(' ... waiting for some time'), and assign it to the TimerFcn of your timer, it takes a copy of the entire current workspace of the function mytest2, including the onCleanup object. The timer is created in the base workspace (not the function workspace), and remains in existence even at the end of the function, along with the onCleanup object, which then never goes out of scope, never gets deleted, its destructor function never runs, and you don't get your message.
Note that:
If you run a = timerfindall; delete(a); in the base workspace, you will get your message, as you've explicitly deleted the timer along with the onCleanup object.
This behaviour about anonymous functions taking a copy of their entire workspace is fully documented, although you may not be aware of it, and although you clearly don't want it to work like that here. It's nasty.
Fortunately, it's easy to work around:
function mytest3(time)
t = timer();
setTimerFcn(t)
myclean = onCleanup(#() disp('function ends'));
pause(time);
end
function setTimerFcn(t)
t.TimerFcn = #(o,s)disp(' ... waiting for some time');
end
Now, when the anonymous function is created it only takes a copy of its local workspace (i.e. from the subfunction setTimerFcn), which does not include the onCleanup object. The onCleanup object goes out of scope at the point you expect it to, and everything's fine.
Hope that helps!
a possible workaround (found by a colleague of me) is to move to definition of the timer into a own function. It is not clear to us why this works but it seems that the definition of a timer in matlab changes the context of some local variables of the function which are not 'deleted' after the function ends as it would be expected from the matlab documentation (Object Life cycle of variables in Matlab)
A working example is shown below (it uses the defined timer to print simple status messages while waiting) and upon Ctrl+c or when the function ends the Timer is stopped. It furthermore makes sure that only one timer with the name 'timer-mywait' is defined.
function mytest3(time)
% register Cleanup handler
c = onCleanup(#()onCleanup_fcn);
t = mywait_timer(time);
wait(t);
% onCleanup handle function
function onCleanup_fcn
tm = timerfind('Name','timer-mywait');
if ~isempty(tm) && any(strcmpi(get(tm,'running'),'on'))
disp('Stopped running timer ''timer-mywait''!');
stop(tm);
end
end % onCleanup_fcn
end %mytest3
function t = mywait_timer(time)
N = 5;
t = timerfind('Name','timer-mywait');
if isempty(t) % avoid multiple definitions of the same timer
t = timer();
end
t.ExecutionMode = 'fixedRate';
t.TasksToExecute = N+1;
t.Period = str2num(sprintf('%.3f',time/N)); % Matlab complains about more digits!
t.Name = 'timer-mywait';
t.TimerFcn = #(o,s)mywait_timercb();
start(t),
end % mywait_timer
function mywait_timercb()
disp(' still waiting ... ');
end % mywait_timercb

return NOT exiting function properly in MATLAB

I'm running a recursive function which searches a room for an object. This code is working in conjunction with another process essentially running the same code. The first thing the code does is check to see if the other one has found the object and, if so, it is supposed to break out of the function.
When I do the check to see if the other process has found the object, if it has, I use "return" to break out of that function at which time it's supposed to move onto other lines of code...However, for some reason it doesn't fully break out but instead just runs the function again and again.
Any ideas on how I can get it to break out?
I would and can provide the code but it's kind of long
EDIT
Parent script
!matlab -r "zz_Mock_ROB2_Find" & distT = 0.3;
Rob1_ObjFound = 0;
matrix = search_TEST_cam(rob, vid, 0.3, XYpos, 'north', stack, matrix, 0);
disp('I"M OUT')
Recursive code
function matrix = search_TEST_cam(rob1, vid, distT, startingPos, currentDir, stack, matrix, bT)
Rob1_ObjFound = 0;
Rob2_ObjFound = 0;
try
load('Rob2_ObjFound.mat', 'Rob2_ObjFound');
catch
end
if(Rob2_ObjFound == 1)
setDriveWheelsCreate(rob1, 0, 0);
disp('ROB_2 FOUND THE OBJECT')
pause(0.5)
BeepRoomba(rob1)
pause(0.5)
setDriveWheelsCreate(rob1, 0, 0);
return
end
Use break to break out of a for or a while loop and terminate execution, i.e., statements after that are ignored. For e.g.,
for i=1:5
if i==3
break
else
fprintf('%u,',i)
end
end
outputs 1,2, and the code terminates when i=3. If you have nested loops, break will only break out of its current loop and move on to the parent loop.
To skip only the current iteration and move on to the next, use continue. Using the same example,
for i=1:5
if i==3
continue
else
fprintf('%u,',i)
end
end
outputs 1,2,4,5,.
Using return in a function just returns control to the parent function/script that called it.
It seems like you're using the wrong one in your code. However, it's hard to tell without knowing how you're using them. Anyway, you can try one of these three and see if it makes a difference.
It's hard to say without seeing your code, but I doubt it's a problem with the RETURN statement. It's more likely a problem with how you've set up your recursion. If your recursive function has called itself a number of times, then when you finally invoke a RETURN statement it will return control from the current function on the stack to the calling function (i.e. a previous call to your recursive function). I'm guessing the calling function doesn't stop the recursion properly and ends up calling itself again, continuing the recursion.
My advice: check the exit conditions for your recursive function to make sure that, when the object is found and the most recent call returns, every previous call is properly informed that it should return as well.