LinkClose[link]
"does not necessarily terminate the program at the other end
of the connection" as it is said in the Documentation. Is there a way to kill the
process of the slave kernel securely?
EDIT:
In really I need a function in Mathematica that returns only when the process of the slave kernel has already killed and its memory has alread开发者_高级运维y released. Both LinkInterrupt[link, 1]
and LinkClose[link]
do not wait while the slave kernel exits. At this moment the only such function is seemed to be killProc[procID]
function I had showed in one of answers at this page. But is there a built-in analog?
At this moment I know only one method to kill the MathKernel
process securely. This method uses NETLink
and seems to work only under Windows and requires Microsoft .NET 2 or later to be installed.
killProc[processID_] := If[$OperatingSystem === "Windows",
Needs["NETLink`"];
Symbol["LoadNETType"]["System.Diagnostics.Process"];
With[{procID = processID},
killProc[procID_] := (
proc = Process`GetProcessById[procID];
proc@Kill[]
);
];
killProc[processID]
];
(*Killing the current MathKernel process*)
killProc[$ProcessID]
Any suggestions or improvements will be appreciated.
Edit:
The more correct method:
Needs["NETLink`"];
LoadNETType["System.Diagnostics.Process"];
$kern = LinkLaunch[First[$CommandLine] <> " -mathlink -noinit"];
LinkRead[$kern];
LinkWrite[$kern, Unevaluated[$ProcessID]];
$kernProcessID = First@LinkRead[$kern];
$kernProcess = Process`GetProcessById[$kernProcessID];
AbortProtect[If[! ($kernProcess@Refresh[]; $kernProcess@HasExited),
$kernProcess@Kill[]; $kernProcess@WaitForExit[];
$kernProcess@Close[]];
LinkClose[$kern]]
Edit 2:
Even more correct method:
Needs["NETLink`"];
LoadNETType["System.Diagnostics.Process"];
$kern = LinkLaunch[First[$CommandLine] <> " -mathlink -noinit"];
LinkRead[$kern];
LinkWrite[$kern, Unevaluated[$ProcessID]];
$kernProcessID = First@LinkRead[$kern];
$kernProcess = Process`GetProcessById[$kernProcessID];
krnKill := AbortProtect[
If[TrueQ[MemberQ[Links[], $kern]], LinkClose[$kern]];
If[TrueQ[MemberQ[LoadedNETObjects[], $kernProcess]],
If[! TrueQ[$kernProcess@WaitForExit[100]],
Quiet@$kernProcess@Kill[]; $kernProcess@WaitForExit[]];
$kernProcess@Close[]; ReleaseNETObject[$kernProcess];
]
];
Todd Gayley has answered my question in the newsgroup. The solution is to send to the slave kernel an MLTerminateMessage
. From
top-level code:
LinkInterrupt[link, 1] (* An undocumented form that lets you pick
the message type *)
In C:
MLPutMessage(link, MLTerminateMessage);
In Java using J/Link:
link.terminateKernel();
In .NET using .NET/Link:
link.TerminateKernel();
EDIT:
I have discovered that in standard cases when using LinkInterrupt[link, 1]
my operating system (Windows 2000 at the moment) releases physical memory
only in 0.05-0.1 second beginning with a moment of execution of
LinkInterrupt[link, 1]
while with LinkClose[link]
it releases physical
memory in 0.01-0.03 second (both values include the time, spent on execution
of the command itself). Time intervals were measured by using SessionTime[]
under equal conditions and are steadily reproduced.
Actually I need a function in Mathematica that returns only when the process of the slave kernel has already killed and its memory has already released. Both LinkInterrupt[link, 1]
and LinkClose[link]
do not wait while the slave kernel exits. At this moment the only such function is seemed to be killProc[procID]
function I had showed in another answer at this page.
精彩评论