Search code examples
wolfram-mathematicamathlink

How to kill slave kernel securely?


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 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 one of answers at this page. But is there a built-in analog?


Solution

  • 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];
        ]
       ];