Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

System.Concurrency.Channel non-deterministic behaviour in Chez-Scheme #1552

Closed
CodingCellist opened this issue Jun 14, 2021 · 0 comments · Fixed by #1596
Closed

System.Concurrency.Channel non-deterministic behaviour in Chez-Scheme #1552

CodingCellist opened this issue Jun 14, 2021 · 0 comments · Fixed by #1596

Comments

@CodingCellist
Copy link
Collaborator

When using a channel to communicate with multiple processes, things sent on the channel can get lost. Small example:

import System.Concurrency

child : Channel Nat -> IO ()
child c =
  do (S k) <- channelGet c
       | Z => putStrLn "Child thread done."
     child c

main : IO ()
main =
  do c <- makeChannel
     tids <- for [1..4] $ \_ => fork (child c)
     ignore $ for [1..8] $ \_ => channelPut c 1
     ignore $ for [1..4] $ \_ => channelPut c Z
     ignore $ traverse (\t => threadWait t) tids
     putStrLn "All threads + main done."

(a more flexible example can be found here)

Steps to Reproduce

Execute main in the code above (or from the gist), first with --cg chez then with --cg racket.

Expected Behavior

No messages are lost and all threads terminate correctly, followed by the main thread terminating.

Observed Behavior

On the Chez-Scheme backend, the behaviour is non-deterministic: Sometimes all the child threads terminate, but more often they don't and so the program never finishes because at least one of the threads in threadWait never receives the Z that was sent.

By contrast, on the Racket backend, the program seems to always behave as expected, suggesting this is a problem with the Channel implementation in support/chez/support.ss.

CodingCellist added a commit to CodingCellist/Idris2 that referenced this issue Jun 21, 2021
The semantics are correct, but the way we achieve them is nasty
(spinning on an `IORef Bool` which eventually gets modified by some
other thread)...
CodingCellist added a commit to CodingCellist/Idris2 that referenced this issue Jul 1, 2021
… cg.

After much discussion and debugging with @zseri, this seems to be the
simplest _fully working_ implementation of Channels under the
Chez-Scheme backend. However, since the main cause of trouble was that
`channelPut` should block until the value had been received, this is no
longer true in the Chez backend. Instead, `channelPut` now only blocks
if there is already a value in the Channel which hasn't been received
yet. This is different to the Racket Channel behaviour, but at least it
consistently works.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants