haskell-distributed / distributed-process

Cloud Haskell core libraries
http://haskell-distributed.github.io
711 stars 96 forks source link

Links are mentioned as unidirectional #448

Open Abhiroop opened 7 years ago

Abhiroop commented 7 years ago

In chapter 3 of the tutorials, links are mentioned to be unidirectional. On the other hand, monitors are the ones which are actually unidirectional (at least in Erlang). Unidirectional in the sense that when one process dies, the monitoring process is not killed, while on the other hand in case of a link both the processes die implying bidirectional nature rather than unidirectional.

facundominguez commented 7 years ago

To say that links are bidirectional would imply that when the linking process dies, the linked process should die as well. The death notification goes in one direction only, and that's why links are considered unidirectional.

Abhiroop commented 7 years ago

@facundominguez Oh I see. This seems to be a bit different from the behavior of links in Erlang. From the book Programming Erlang[1] by Joe Armstrong

Monitors are unidirectional. If A monitors B and B dies, then A will be sent an exit message but not the other way around (recall that links were bidirectional, so if A and B were linked, the death of either process would result in the other process being informed).

[1]https://www.safaribooksonline.com/library/view/programming-erlang-2nd/9781941222454/f_0117.html

Abhiroop commented 7 years ago

After running an example with link in Cloud Haskell, I find that the behavior is partially similar to that of Erlang, in that when I link a process A with process B and if process B dies, A dies too. I haven't checked the other way round.

To say that links are bidirectional would imply that when the linking process dies, the linked process should die as well.

So are you telling suppose I call the link function from process A and link to process B, and suppose process A dies, then B does not die?

facundominguez commented 7 years ago

So are you telling suppose I call the link function from process A and link to process B, and suppose process A dies, then B does not die?

That's what I would expect to happen.

Abhiroop commented 7 years ago

@facundominguez You are right, I verified this behavior with a simple program

demo3 :: Process ()
demo3 = do
  pid1 <- spawnLocal process1
  pid2 <- spawnLocal process2
  send pid2 pid1
  send pid1 pid2
  sleepFor 5 Seconds
  send pid2 "hello"
  () <- expect
  return ()
 where
   process1 = do
     proc2 <- expect :: Process ProcessId
     link proc2
     return ()
   process2 = do
     proc1 <- expect :: Process ProcessId
     expectingFromMain <- expect :: Process String
     (say.show) expectingFromMain
     return ()

In the above program despite of the process1 dying process2 stays alive and receives the expected "hello" string from the main thread and prints it to the console. However if we change the program a little and call link from process2 then the process dies.

I just wonder what thought went behind this design decision and to differ it from Erlang. I can see the original paper taking an approach similar to Erlang:

linkProcess corresponds to Erlang’s link . It establishes bidirectional process monitoring between the current process and a given process; if either of those processes terminate abnormally, the other will receive an asynchronous exception. linkProcess is defined in terms of monitorProcess.

So why was the design of the current link made different?

hyperthunk commented 6 years ago

There's a separate primitive for that, in the -extras library. The authors of the original distributed-process implementation agreed that since the formal semantics do not cover bidirectional linking, it should not be implemented. We'd need to fix the semantics first. The reason the semantics don't have explicit support for this is that it can only be guaranteed to work for intra-node peer processes.