I don't understand how you are meant to use onCleanup in a script

I am struggling to understand how to use onCleanup in a script. I have read the help files pretty thoroughly, looked through some other answers on the forum (e.g. https://uk.mathworks.com/matlabcentral/answers/12536-oncleanup-and-script?s_tid=srchtitle, https://uk.mathworks.com/matlabcentral/answers/600571-how-to-use-oncleanup?s_tid=srchtitle) and attempted my own code, but it seems incompatible with what I am trying to achieve. All that I want to do is to perform some tasks when I push CTRL+C or STOP on the taskbar.
I understand that the onCleanup fires when the variable goes out of scope. But then how do you use it in a script that is calling functions? E.g. some psuedo-code below, my main script runs along doing things, sometimes calling a helper function for a discrete complicated bit of code. At that point the cleanup fires because I have now changed workspace.
function MyScriptName()
sPort = serialport("COM4",57600);
fopen(sPort);
cleanupObj = onCleanup(@()ShutDown(sPort));
% Do thing here
% Do another thing
[x,y] = HelperFunction %Cleanup routine will fire on this line
while true
% Do things repetitively until I terminate
[a,b] = AnotherHelperFunction
end
end
x, y = function HelperFunction()
% Do something specific
end
a, b = function AnotherHelperFunction()
% Do something specific
end
% Close down gracefully and safely
function ShutDown(sPort)
write(sPort,data, "uint8");
write(sPort,data, "uint8");
end
So what am I missing? Is it just not possible in my use case? And why does it seem so complicated to just have a top-level "On Stop run this code"?
EDIT: I should add that I first tried it without a main function, but then it seemed to execute immediately. However the first article I linked above said that I needed to use it within a function, so I changed the main body into a function.
Many thanks,
Robyn

5 comentarios

"I am struggling to understand how to use onCleanup in a script"
Your code consists entirely of functions, no scripts anywhere.
"At that point the cleanup fires because I have now changed workspace."
The function ShutDown is called because cleanupObj is destroyed, exactly as documented. If the code runs to completion then cleanupObj will be destroyed at the end of MyFun:
MyFun()
Name Size Bytes Class Attributes cleanupObj 1x1 8 onCleanup Name Size Bytes Class Attributes X 1x1 8 double cleanupObj 1x1 8 onCleanup This is called only when cleanupObj is destroyed
function MyFun()
cleanupObj = onCleanup(@ShutDown);
whos
X = HelperFunction; % cleanupObj is not destroyed here !!!!
whos
end
function out = HelperFunction()
out = pi;
end
function ShutDown()
disp('This is called only when cleanupObj is destroyed')
end
Within which function is the code currently executing when you try ctrl+c ?
Hi Stephen,
I am not sure whether you read my edit, but it is a .m file with a few hundred lines of code and some helper functions at the bottom. I only changed the main body of code to be a function based on what I read in othe answers (https://uk.mathworks.com/matlabcentral/answers/12536-oncleanup-and-script?s_tid=srchtitle). But I made that change because when running the body as a script, it would immediatly jump to that cleanup function. Below is how it was when I first tried it, but it seemed to just fire straight away.
sPort = serialport("COM4",57600);
fopen(sPort);
cleanupObj = onCleanup(@()ShutDown(sPort));
% Do thing here
% Do another thing
[x,y] = HelperFunction
while true
% Do things repetitively until I terminate
[a,b] = AnotherHelperFunction
end
--------------------------------------------------------------------------------------
%% Helper Functions
x, y = function HelperFunction()
% Do something specific
end
a, b = function AnotherHelperFunction()
% Do something specific
end
% Close down gracefully and safely
function ShutDown(sPort)
write(sPort,data, "uint8");
write(sPort,data, "uint8");
end
I am used to C, where I have a body of code, part of which will likely be in a loop, and at some point I break out of that loop and cleanup/perform shutdown tasks. That is what I am trying to replicate here.
Within which function is the code currently executing when you try ctrl+c ?
It could be anywhere. I call libraries written by MathWorks for my particular piece of hardware from the body of the code, so normally when I hit stop I get an error of various flavours saying the code failed in one function or another, I assume due to unexpected termination. (to be clear, everything is working as expected, it is only an error on stop which seems standard, as even their demo scripts do the same).
The object will get destroyed regardless of any loops calling local functions:
MyFun1()
before after This is called only when cleanupObj is destroyed
And it will also get destroyed when the local function throws an error:
MyFun2()
before This is called only when cleanupObj is destroyed
Error using assert
Assertion failed.

Error in solution>HelpFun2 (line 28)
assert(toc(t)<1)
^^^^^^^^^^^^^^^^
Error in solution>MyFun2 (line 22)
X = HelpFun2(t);
^^^^^^^^^^^^^^^^
function MyFun1()
cleanupObj = onCleanup(@ShutDown);
t = tic();
x = true;
disp before
while x
x = HelpFun1(t);
end
disp after
end
function out = HelpFun1(t)
out = toc(t)<1;
end
function MyFun2()
cleanupObj = onCleanup(@ShutDown);
t = tic();
disp before
while true
X = HelpFun2(t);
end
disp after
end
function out = HelpFun2(t)
out = pi;
assert(toc(t)<1)
end
function ShutDown()
disp('This is called only when cleanupObj is destroyed')
end
Of course this forum does not support ctrl+c, so I tried this in the app:
function MyFun3()
cleanupObj = onCleanup(@ShutDown);
disp before
while true
X = HelpFun3();
end
disp after
end
function out = HelpFun3()
out = pi;
end
function ShutDown()
disp('This is called only when cleanupObj is destroyed')
end
pressed ctrl+c and got this output:
>> MyFun3
before
This is called only when cleanupObj is destroyed
Operation terminated by user during MyFun3 (line 5)
So far everything seems to be working as expected.
Rather than pseudo-code, please create an MWE the demonstrates the behavior you are observing, and explain exactly what behavior you expect with that MWE.
Hi Stephen,
Thanks for your further reply. I am not sure what a MWE is, and googling it doesn't bring up any obvious answers. But if it is some sort of web example code, I unfortunately do not have time to code anything else up, my dissertation is due in less than 2 weeks, so I will just have to live with the behaviour and manually run cleanup commands from the console. I was expecting to have missed something obvious and had hoped I could make a quick change to rectify it.
Thanks for your input in any case.
Regards
Stephen23
Stephen23 el 10 de Jul. de 2025
Editada: Stephen23 el 10 de Jul. de 2025

Iniciar sesión para comentar.

Respuestas (1)

The purpose of an onCleanup object is to execute the function handle with which it was created when the onCleanup object gets destroyed. If you create the onCleanup object inside a function, assuming the onCleanup object is not returned from that function [1], the object will be destroyed under one of three circumstances.
  1. The function completes its execution normally, and its workspace (including the object) gets destroyed as part of the function returning to its caller.
  2. The function terminate due to an uncaught error or Ctrl-C interrupt, and its workspace gets destroyed as part of the function returning to the Command Window prompt.
  3. You explicitly delete or overwrite the variable.
If you create the onCleanup object inside a script file, it doesn't have its own workspace so circumstances 1 and 2 don't apply. You'd need to explicitly destroy the onCleanup object with clear or delete. You could also overwrite it.
x = onCleanup(@() disp("Goodbye"));
x = 42
Goodbye
x = 42
y = onCleanup(@() disp("Farewell cruel world!"));
delete(y)
Farewell cruel world!
FYI, the term "MWE" stands for Minimal Working Example: a small (ideally the smallest) example that others can run to reproduce the behavior you're seeing. What I wrote above is two MWEs, one showing the overwrite case (the x MWE) and the other showing the delete case (the y MWE)
[1] There are a few other ways it could be kept alive, but they're probably rarer. One that might apply in your case is storing the onCleanup in a property of an object that "survives" the function exit, like the UserData property of a figure window.

Categorías

Más información sobre Startup and Shutdown en Centro de ayuda y File Exchange.

Productos

Versión

R2024b

Etiquetas

Preguntada:

el 10 de Jul. de 2025

Respondida:

el 10 de Jul. de 2025

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by