Skip to content

Commit 465f841

Browse files
authored
ensure fn passed to generator completes (#318)
This avoids forcing the generator to abort, which is not thread-safe.
1 parent bcf4e84 commit 465f841

File tree

3 files changed

+31
-8
lines changed

3 files changed

+31
-8
lines changed

src/rt/mod.rs

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -192,9 +192,6 @@ pub fn thread_done() {
192192
execution.threads.active_mut().operation = None;
193193
execution.threads.active_mut().set_terminated();
194194
let switch = execution.schedule();
195-
196195
trace!(?thread, ?switch, "thread_done: terminate");
197-
198-
switch
199196
});
200197
}

src/rt/scheduler.rs

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,11 @@ impl Scheduler {
8383
threads[0].resume();
8484

8585
loop {
86-
if !execution.threads.is_active() {
86+
if execution.threads.is_complete() {
87+
for thread in &mut threads {
88+
thread.resume();
89+
assert!(thread.is_done());
90+
}
8791
return;
8892
}
8993

@@ -131,12 +135,17 @@ impl Scheduler {
131135
fn spawn_thread(f: Box<dyn FnOnce()>, stack_size: Option<usize>) -> Thread {
132136
let body = move || {
133137
loop {
134-
let f: Option<Box<dyn FnOnce()>> = generator::yield_(()).unwrap();
135-
generator::yield_with(());
136-
f.unwrap()();
138+
let f: Option<Option<Box<dyn FnOnce()>>> = generator::yield_(());
139+
140+
if let Some(f) = f {
141+
generator::yield_with(());
142+
f.unwrap()();
143+
} else {
144+
break;
145+
}
137146
}
138147

139-
// done!();
148+
generator::done!();
140149
};
141150
let mut g = match stack_size {
142151
Some(stack_size) => Gn::new_opt(stack_size, body),

src/rt/thread.rs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -234,6 +234,23 @@ impl Set {
234234
self.active.is_some()
235235
}
236236

237+
pub(crate) fn is_complete(&self) -> bool {
238+
if self.active.is_none() {
239+
// All threads should be terminated
240+
for thread in &self.threads {
241+
assert!(
242+
thread.is_terminated(),
243+
"thread not terminated; {:#?}",
244+
thread
245+
);
246+
}
247+
248+
true
249+
} else {
250+
false
251+
}
252+
}
253+
237254
pub(crate) fn active_id(&self) -> Id {
238255
Id::new(self.execution_id, self.active.unwrap())
239256
}

0 commit comments

Comments
 (0)