CheckAbort inside MathLink functions?
Asked Answered
D

1

12

I just found that such MathLink functions as LinkWrite and LinkRead have something like its own internal CheckAbort that absorbs any aborts, and does not propagate them further.

This can be easily shown with LinkRead:

link = LinkLaunch[First[$CommandLine] <> " -mathlink"];
LinkRead[link];
LinkWrite[link, Unevaluated[Pause[10]]];
{LinkRead[link], Print["!!"]}

After evaluating the above code press Alt+. and you will get the following output:

During evaluation of In[6]:= !!
Out[9]= {ReturnPacket[$Aborted], Null}

As you see the abort was absorbed by LinkRead.

My problem is that it breaks my own flow control of evaluation based on CheckAbort.

Is there a way to intercept aborts absorbed by such functions as LinkRead and LinkWrite?

Durkee answered 12/4, 2011 at 13:39 Comment(5)
Your question is the 666th with the mathematica tag. Isn't that scary?Numskull
@belisarius It is cool! Thank you for pointing this out! How can I check this?Durkee
on this page, upper right corner, just below the Ask Question buttonNumskull
@belisarius, I always thought MathLink was a bit evil, so this just proves it ...Clotho
After getting soaked by rain, my previous cellphone incessantly typed '666, 666 ...'. Actually, just 6's, but I liked this devilish interpretation better. This was just the incentive I needed to switch to an iPhone. ;-)Noachian
G
1

The way MathLink works, LinkRead blocks if there is nothing to read on the link. If you try to abort at this time, an abort message is passed via MathLink message channel to the other end of the link. If the program on the other end behaves nicely, it will drop whatever it was doing and send a return value (in many cases $Aborted). If you want to propagate the abort to your end of the link, so that you can catch it with CheckAbort, you will need to check the return value and generate another abort, for example:

 If[LinkRead[link] == $Aborted, Abort[]]

This works if you know that the other end of the link returns $Aborted in case it is aborted.

Graminivorous answered 20/11, 2014 at 15:11 Comment(9)
When at the other end of the link is MathKernel, can be I sure that it will always return $Aborted when LinkRead passes it an abort message? Is this behavior reliable?Durkee
As far as I know, MathKernel always returns $Aborted if the evaluation is aborted. However, an abort message might not always abort the evaluation before the evaluation finishes. In these cases a valid result is returned.Graminivorous
So there are two situations: 1. The evaluation is aborted and $Aborted is returned; 2. The abort is absorbed without any effect. In the latter situation, is it possible to quit the kernel at the other end of the link without quitting the master kernel?Durkee
If LinkRead is blocking on your end, and you close the link from the remote end, LinkRead returns $Failed. If the remote kernel is quit gracefully, it will close the link for you. If you kill the remote kernel, LinkRead should still return $Failed, but I'm not sure whether you can trust that to happen every time.Graminivorous
It looks like we cannot rely on the behavior of both LinkRead and the remote kernel. As I see it, the key problem is that we cannot intercept the abort in the master kernel: being able to do this we would have many ways to close the remote kernel or send it an interrupt message or kill it.Durkee
Up to this time I was forced to use the following workaround: do not go into the LinkRead blocking but instead use LinkReadyQ 10 times per second for checking the state of the remote kernel. This workaround suffer from the same problem: if the abort appears while LinkReadyQ is executed, it will be absorbed and will not be intercepted in the master kernel. With LinkReadyQ this happens rarely, but I am still unhappy with this workaround.Durkee
If you operate the kernel directly, instead of through the notebook interface, it is possible to send the abort directly to the master kernel or even kill the remote kernel so that LinkRead reliably returns $Failed. Is this an option for you?Graminivorous
My goal is to stop evaluation completely when a user generates abort. The ideal solution would go through the steps: 1) try to abort the remote kernel then 2) kill it if it does not respond and finally 3) abort evaluation in the master kernel. Of course manual closing the remote kernel by means of the OS is possible but I would like to avoid doing so.Durkee
Let us continue this discussion in chat.Graminivorous

© 2022 - 2024 — McMap. All rights reserved.