# Is it possible to set a timeout for LinkWrite[]?

This came up in relation to this answer

Is it possible to set a timeout for LinkWrite? LinkWrite seems to block until the sent data is read on the other end of the link. Can it block indefinitely or does it have a long timeout? If it doesn't have a default timeout, is it possible to set one?

### An example

Let's create two new kernels in the front end (this might overwrite your existing kernels, but it will be reversed after restarting the front end):

SetOptions[$FrontEndSession, EvaluatorNames -> {"Local" -> {"AutoStartOnLaunch" -> True}, "K1" -> {"AutoStartOnLaunch" -> False}, "K2" -> {"AutoStartOnLaunch" -> False}}]  Then open two new notebooks, and in the first one evaluate SetOptions[EvaluationNotebook[], Evaluator -> "K2"] link = LinkCreate["alink"] LinkWrite[link, "boo"]  In the second one evaluate SetOptions[EvaluationNotebook[], Evaluator -> "K1"] link = LinkConnect["alink"] LinkRead[link]  LinkWrite in the first one will only return after LinkRead has finished evaluating in the second one. If the answer is that it's not possible to set a timeout, that can be reasonable too. I was wondering about this: suppose we're running a long parallel calculation, and we interrupt the main kernel to enter a subsession and inspect the state (Evaluation -> Interrupt -> Enter subsession). Is it possible that one of the parallel kernels will time out while trying to send the result, and the calculation won't be able to resume after returning from the subsession? - Have you tried wrapping the LinkWrite in a TimeConstrained call? – Arnoud Buzing Jan 31 '12 at 19:32 To address the last part of your question separately--yes, it probably will time out; the timeout period is set by ParallelSettings$MathLinkTimeout and has a default value of 15 seconds. May I also suggest that you consider changing the title of this question, given that LinkWrite is non-blocking on a properly initialized MathLink connection? (To flush the message queues, one would use LinkFlush, which is blocking until the messages have been sent.) – Oleksandr R. Jan 31 '12 at 21:07
@OleksandrR. I have seen the 15 timeout when parallel kernels fail to launch. But in a quick test, if they do launch correctly, they don't seem to be affected, no matter how long I keep the master kernel paused in a Dialog[]. I still don't feel confident enough about this interrupting a long calculation and going into a dialog, but at least in those simple tests I did it seemed to work without issues. – Szabolcs Feb 1 '12 at 13:11

Setting up MathLink connections between kernels acting as peers (as opposed to in a master-slave arrangement) is sparsely documented, and the critical function you need to make this work, i.e. LinkActivate, is undocumented altogether (although, if you clear its ReadProtected attribute, you will see that it is merely a synonym for LinkConnect, which itself is a version of LinkOpen). In fact, LinkRead and LinkWrite both work with message queues and are not inherently blocking operations, but the behaviour you see is the result of the MathLink connection not having been initialized properly before writing.

To initialize the connection correctly, modify your code as follows:

SetOptions[EvaluationNotebook[], Evaluator -> "K2"]

(* No longer blocks *)


and

SetOptions[EvaluationNotebook[], Evaluator -> "K1"]

(* Evaluate immediately after calling LinkCreate from K2. *)



Why this is undocumented I do not know; to my knowledge the only place where this is described is the (rather specialist) book, MathLink: Network Programming with Mathematica by Chikara Miyaji and Paul Abbott. I discovered it when I was curious as to whether it was possible to write an MPI-style message-passing implementation in pure Mathematica. (The answer is yes; I posted some code on MathGroup here if you are interested.)

-
So after creating the link, I need to connect from both sides. You explanation makes it much more clear how these work. – Szabolcs Jan 31 '12 at 20:45
It seems that LinkActivate is not just a synonym of LinkConnect for any argument type. If I try to use only LinkConnect in its place, this example won't work. Got to get some sleep, will play more tomorrow. – Szabolcs Jan 31 '12 at 20:53
Hmm, I hadn't tried that so not sure. Also, note that although some operations seem to work without it, if you don't call LinkActivate/LinkConnect after setting up a peer-to-peer link, you'll usually find that LinkReadyQ gives incorrect results. Obviously this is a problem if you want to avoid blocking. – Oleksandr R. Jan 31 '12 at 20:55
@OleksandrR. LinkReadyQ isn't returning incorrect results. It has a different meaning for unconnected links. LinkReadyQ for an unconnected link tells you whether the other side of the link exists and is ready to be connected. E.g., if you've opened a listening link, there's no guarantee that the other side exists, and polling it with LinkReadyQ may be useful to determine whether calling LinkActivate (or LinkConnect with a LinkObject argument) could hang indefinitely. That's still technically possible, of course, if the other side doesn't connect the link, but less likely. – John Fultz Feb 29 '12 at 6:08
@OleksandrR. yes, you're probably right that it's not documented...but I doubt it will ever change, as these behaviors are well-known within WRI and probably frequently relied upon. For example, the FE relies upon this behavior of MLReady(). I don't know whether MLReadyParallel() has the same behavior or not. The FE uses MLReadyParallel() extensively (well, only in one place, but that place is executed all the time), but only with links that are already connected. I'm not aware of any significant and recent bug fixes to it. – John Fultz Mar 6 '12 at 2:48

You can wrap the LinkWrite in TimeConstrained as:

TimeConstrained[LinkWrite[link, "boo"], t]


where t is the number of seconds you'd like to wait before it times out. You can also add a default command to evaluate if it fails, using the third argument.

TimeConstrained[LinkWrite[link, "boo"], t, Print["Timed out."]]

-