Reputation: 613311
tl;dr
Is there any way in a Matlab .m file to detect that Matlab termination is under way?
I have an unmanaged library that provides an interface to my product. I have wrapped that for Matlab using a mex file. So my unmanaged library exists as a Windows DLL. I have a mex file that wraps that. In turn I have a collection of Matlab classes, implemented in various .m files that wrap the mex file. So far so good, all of this works splendidly.
I recently became aware of a problem during Matlab shutdown. Some of the Matlab classes wrap unmanaged objects. These unmanaged objects need to be destroyed when they are no longer needed. So I implement delete
functions for the Matlab classes that wrap the unmanaged objects, and call into the mex file to destroy the objects. Obviously the mex file simply forwards these destruction calls to the unmanaged library. Again, this all works just fine.
The problem arises when Matlab shuts down and the user's workspace contains Matlab objects wrapping the unmanaged objects. Unfortunately, Matlab unloads the mex file, and then destroys the objects in the workspace. What happens next is that the delete
function executes which calls into the mex file. Which reloads the mex file that was just unloaded. And now the attempt to destroy the unmanaged object leads to runtime errors, because my library has to be re-loaded.
Since is going to unload the mex file before destroying workspace objects, I have no choice but to skip the deletion of the unmanaged objects in that scenario. It isn't a memory leak or indeed a problem in any way, since the process is terminating. However, I do need to detect that the process is terminating. Which leads to the question, how to do that.
I'm aware of the finish.m
termination file, but I'm not in control of that since I am providing a library. The user controls their termination file, and so I've ruled out that option. I don't even know whether or not it runs at a suitable time, i.e. before the workspace objects are destroyed.
I've built a functioning solution using mexAtExit
. In the mex file initialization I call mexAtExit
like so:
mexAtExit(atExit);
The atExit
function is:
void atExit(void)
{
mexCallMATLAB(0, NULL, 0, NULL, "mylib.atExit");
}
And ofx.atExit
is in the Matlab code and is implemented like this:
methods(Static)
function atExit
mylib.mexHasUnloaded(true);
end
function result = mexHasUnloaded(varargin)
global mexHasUnloadedGlobalVar;
if isempty(mexHasUnloadedGlobalVar)
mexHasUnloadedGlobalVar = false;
end
if nargin > 0
mexHasUnloadedGlobalVar = varargin{1};
end
result = mexHasUnloadedGlobalVar;
end
....
end
The delete
function then checks mexHasUnloaded
like this:
function delete(self)
if ~mylib.mexHasUnloaded
mylibMex(mylib.mexDestroyObject, self.handle);
end
end
Whilst this appears to work, I'm not at all happy with it.
persistent
variable but that was just as hacky and did not work. The persistent
variable was re-initialised at some point during the termination which meant that mexHasUnloaded
started returning false
after it had earlier been set to true
.Upvotes: 3
Views: 243
Reputation: 25160
Does it work to mexLock()
your MEX file so that it doesn't get unloaded, so the delete
methods can do the right thing at shutdown?
Upvotes: 3