core.async

Waiters should unblock on close!

Details

  • Type: Defect Defect
  • Status: Resolved Resolved
  • Priority: Major Major
  • Resolution: Declined
  • Affects Version/s: None
  • Fix Version/s: None
  • Component/s: None
  • Labels:
    None

Description

Expected behavior

When a channel is closed, all readers and writers waiting for it, whether on a thread with the !! family of functions or in a go block, should unblock and return nil, as if the channel had been closed in the first place. This is expected since channels are frequently discarded after being closed.

Problem description

The operator >!! (used as example here) immediately returns, when used on a closed channel, however, if >!! is already waiting for a channel, which is then closed, >!! doesn't unblock. , stalling the thread indefinitely.
EDIT: The thread/go block can still be unblocked, by taking from the channel, however since close! signifies the end of the lifetime of a channel, subsequent takes on it cannot be considered idiomatic.

Example REPL Sessions

In this example, the future blocks indefinitely, even though the target channel is closed

This is a problem, since the >!! might be called in a try..catch holding resources and such.

The example also shows, that values can be read from a closed channel (and trigger processing), which might be ok for channel buffers, not so much for pending >!! that have side effects in their continuation.

> (def ch (async/chan))
> (future (>!! ch :cool)
          (println "done"))
> (<!! ch)
"done"
:cool
> (future (>!! ch :cool)
          (println "done"))
> (close! ch)
;; FIXME "done" should be printed here
> (<!! ch)
"done" ;; EDIT pending >!! can be taken from, same as with >!
nil
> (future (>!! ch :cool)
          (println "done"))
;; Same as here
"done"

EDIT Removed example documenting different behavior of threads and go blocks, since subsequent tests turned them out to behave the same.

References

This was first posted to github https://github.com/clojure/core.async/issues/36
Some discussion already happenend there.

http://dev.clojure.org/jira/browse/ASYNC-31 seems related with regard to the close! semantics of a write.

Activity

Herwig Hochleitner made changes -
Field Original Value New Value
Description h1. Expected behavior

When a channel is closed, all readers and writers waiting for it, whether on a thread with the !! family of functions or in a go block, should unblock and return nil, as if the channel had been closed in the first place.

h1. Problem description

The operator >!! (used as example here) immediately returns, when used on a closed channel, however, if >!! is already waiting for a channel, which is then closed, >!! doesn't unblock, stalling the thread indefinitely.

h2. Example REPL Sessions

h3. In this example, the future blocks indefinitely, even though the target channel is closed

{code}
> (def ch (async/chan))
> (future (>!! ch :cool)
          (println "done"))
> (<!! ch)
"done"
:cool
> (future (>!! ch :cool)
          (println "done"))
> (close! ch)
;; FIXME "done" should be printed here
> (<!! ch)
nil
> (future (>!! ch :cool)
          (println "done"))
;; Same as here
"done"
{code}

h3. In go blocks, the >! doesn't unblock either, but can still be unblocked by using <!! after close, also triggering the side effects.

This is even more surprising, but might be explained by the docstring of close! about data staying in the channel.

{code}
> (go (>! ch :cool)
      (println ";; Well, ACTUALLY, triggering side effects through a closed channel is not cool"))
> (close! ch)
> (<!! ch)
:cool
;; Well, ACTUALLY, triggering side effects through a closed channel is not cool
{code}

h1. References

This was first posted to github https://github.com/clojure/core.async/issues/36
Some discussion already happenend there.

http://dev.clojure.org/jira/browse/ASYNC-31 seems related with regard to the close! semantics of a write.
h1. Expected behavior

When a channel is closed, all readers and writers waiting for it, whether on a thread with the !! family of functions or in a go block, should unblock and return nil, as if the channel had been closed in the first place. This is expected since channels are frequently discarded after being closed.

h1. Problem description

The operator >!! (used as example here) immediately returns, when used on a closed channel, however, if >!! is already waiting for a channel, which is then closed, >!! doesn't unblock. -, stalling the thread indefinitely.-
EDIT: The thread/go block can still be unblocked, by taking from the channel, however since close! signifies the end of the lifetime of a channel, subsequent takes on it cannot be considered idiomatic.

h2. Example REPL Sessions

h3. In this example, the future blocks -indefinitely-, even though the target channel is closed
This is a problem, since the >!! might be called in a try..catch holding resources and such.

The example also shows, that values can be read from a closed channel (and trigger processing), which might be ok for channel buffers, not so much for pending >!! that have side effects in their continuation.

{code}
> (def ch (async/chan))
> (future (>!! ch :cool)
          (println "done"))
> (<!! ch)
"done"
:cool
> (future (>!! ch :cool)
          (println "done"))
> (close! ch)
;; FIXME "done" should be printed here
> (<!! ch)
"done" ;; EDIT pending >!! can be taken from, same as with >!
nil
> (future (>!! ch :cool)
          (println "done"))
;; Same as here
"done"
{code}

h4. EDIT Removed example documenting different behavior of threads and go blocks, since subsequent tests turned them out to behave the same.

h1. References

This was first posted to github https://github.com/clojure/core.async/issues/36
Some discussion already happenend there.

http://dev.clojure.org/jira/browse/ASYNC-31 seems related with regard to the close! semantics of a write.
Summary Waiters don't onblock on close! Waiters should unblock on close!
Timothy Baldridge made changes -
Resolution Declined [ 2 ]
Assignee Rich Hickey [ richhickey ] Timothy Baldridge [ halgari ]
Status Open [ 1 ] Resolved [ 5 ]

People

Vote (1)
Watch (3)

Dates

  • Created:
    Updated:
    Resolved: