David Heffernan
David Heffernan

Reputation: 613311

Can I detect MATLAB termination other than by way of a mex file mexAtExit handler?

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.

Upvotes: 3

Views: 243

Answers (1)

Edric
Edric

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

Related Questions