diff options
| author | Michael Bebenita <mbebenita@mozilla.com> | 2010-08-17 23:21:29 -0700 |
|---|---|---|
| committer | Michael Bebenita <mbebenita@mozilla.com> | 2010-08-17 23:49:57 -0700 |
| commit | 7ff39ea448c60e5ab993bb4a32649e60de13184d (patch) | |
| tree | 8ef06fded3f193456304245b4339b888897a73db /src/rt/rust_upcall.cpp | |
| parent | 6e9f0f952d758bae2b530c2c9b780f2addf10207 (diff) | |
| download | rust-7ff39ea448c60e5ab993bb4a32649e60de13184d.tar.gz rust-7ff39ea448c60e5ab993bb4a32649e60de13184d.zip | |
Fixed deadlock by removing channel flushing.
Diffstat (limited to 'src/rt/rust_upcall.cpp')
| -rw-r--r-- | src/rt/rust_upcall.cpp | 39 |
1 files changed, 14 insertions, 25 deletions
diff --git a/src/rt/rust_upcall.cpp b/src/rt/rust_upcall.cpp index 7f9f0db1c6d..fb85233c570 100644 --- a/src/rt/rust_upcall.cpp +++ b/src/rt/rust_upcall.cpp @@ -108,29 +108,7 @@ upcall_new_chan(rust_task *task, rust_port *port) { extern "C" CDECL void upcall_flush_chan(rust_task *task, rust_chan *chan) { LOG_UPCALL_ENTRY(task); - rust_dom *dom = task->dom; - task->log(rust_log::UPCALL | rust_log::COMM, - "flush chan: 0x%" PRIxPTR, chan); - - if (chan->buffer.is_empty()) { - return; - } - - // We cannot flush if the target port was dropped. - if (chan->is_associated() == false) { - return; - } - - A(dom, chan->is_associated(), - "Channel should be associated to a port."); - - A(dom, chan->port->is_proxy() == false, - "Channels to remote ports should be flushed automatically."); - - // Block on the port until this channel has been completely drained - // by the port. - task->block(chan->port); - task->yield(2); + // Nop. } /** @@ -149,8 +127,19 @@ extern "C" CDECL void upcall_del_chan(rust_task *task, rust_chan *chan) { "Channel's ref count should be zero."); if (chan->is_associated()) { - A(task->dom, chan->buffer.is_empty(), - "Channel's buffer should be empty."); + // We're trying to delete a channel that another task may be reading + // from. We have two options: + // + // 1. We can flush the channel by blocking in upcall_flush_chan() + // and resuming only when the channel is flushed. The problem + // here is that we can get ourselves in a deadlock if the parent + // task tries to join us. + // + // 2. We can leave the channel in a "dormnat" state by not freeing + // it and letting the receiver task delete it for us instead. + if (chan->buffer.is_empty() == false) { + return; + } chan->disassociate(); } delete chan; |
