@@ -108,29 +108,7 @@ upcall_new_chan(rust_task *task, rust_port *port) {
108
108
extern " C" CDECL void
109
109
upcall_flush_chan (rust_task *task, rust_chan *chan) {
110
110
LOG_UPCALL_ENTRY (task);
111
- rust_dom *dom = task->dom ;
112
- task->log (rust_log::UPCALL | rust_log::COMM,
113
- " flush chan: 0x%" PRIxPTR, chan);
114
-
115
- if (chan->buffer .is_empty ()) {
116
- return ;
117
- }
118
-
119
- // We cannot flush if the target port was dropped.
120
- if (chan->is_associated () == false ) {
121
- return ;
122
- }
123
-
124
- A (dom, chan->is_associated (),
125
- " Channel should be associated to a port." );
126
-
127
- A (dom, chan->port ->is_proxy () == false ,
128
- " Channels to remote ports should be flushed automatically." );
129
-
130
- // Block on the port until this channel has been completely drained
131
- // by the port.
132
- task->block (chan->port );
133
- task->yield (2 );
111
+ // Nop.
134
112
}
135
113
136
114
/* *
@@ -149,8 +127,19 @@ extern "C" CDECL void upcall_del_chan(rust_task *task, rust_chan *chan) {
149
127
" Channel's ref count should be zero." );
150
128
151
129
if (chan->is_associated ()) {
152
- A (task->dom , chan->buffer .is_empty (),
153
- " Channel's buffer should be empty." );
130
+ // We're trying to delete a channel that another task may be reading
131
+ // from. We have two options:
132
+ //
133
+ // 1. We can flush the channel by blocking in upcall_flush_chan()
134
+ // and resuming only when the channel is flushed. The problem
135
+ // here is that we can get ourselves in a deadlock if the parent
136
+ // task tries to join us.
137
+ //
138
+ // 2. We can leave the channel in a "dormnat" state by not freeing
139
+ // it and letting the receiver task delete it for us instead.
140
+ if (chan->buffer .is_empty () == false ) {
141
+ return ;
142
+ }
154
143
chan->disassociate ();
155
144
}
156
145
delete chan;
0 commit comments