How to kill slave kernel securely?

前提是你 提交于 2019-12-05 14:41:00

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.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!