Skip to content

Commit af7b769

Browse files
committed
[3/4 for #2365, #2671] Fix exit/kill race with scheds during rust_kernel::fail
1 parent 18c645a commit af7b769

File tree

4 files changed

+15
-12
lines changed

4 files changed

+15
-12
lines changed

src/rt/rust_kernel.cpp

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -162,7 +162,7 @@ rust_kernel::wait_for_schedulers()
162162
rust_scheduler *sched = iter->second;
163163
sched_table.erase(iter);
164164
sched->join_task_threads();
165-
delete sched;
165+
sched->deref();
166166
if (sched_table.size() == 1) {
167167
KLOG_("Allowing osmain scheduler to exit");
168168
// It's only the osmain scheduler left. Tell it to exit
@@ -197,30 +197,29 @@ rust_kernel::fail() {
197197
#if defined(__WIN32__)
198198
exit(rval);
199199
#endif
200-
// Copy the list of schedulers so that we don't hold the lock while
201-
// running kill_all_tasks.
202200
// I think this only needs to be done by one task ever; as it is,
203201
// multiple tasks invoking kill_all might get here. Currently libcore
204202
// ensures only one task will ever invoke it, but this would really be
205203
// fine either way, so I'm leaving it as it is. -- bblum
206-
// FIXME (#2671): There's a lot that happens under kill_all_tasks,
207-
// and I don't know that holding sched_lock here is ok, but we need
208-
// to hold the sched lock to prevent the scheduler from being
209-
// destroyed while we are using it. Probably we need to make
210-
// rust_scheduler atomicly reference counted.
204+
205+
// Copy the list of schedulers so that we don't hold the lock while
206+
// running kill_all_tasks. Refcount to ensure they stay alive.
211207
std::vector<rust_scheduler*> scheds;
212208
{
213209
scoped_lock with(sched_lock);
210+
// All schedulers created after this flag is set will be doomed.
214211
killed = true;
215212
for (sched_map::iterator iter = sched_table.begin();
216213
iter != sched_table.end(); iter++) {
214+
iter->second->ref();
217215
scheds.push_back(iter->second);
218216
}
219217
}
220218

221219
for (std::vector<rust_scheduler*>::iterator iter = scheds.begin();
222220
iter != scheds.end(); iter++) {
223221
(*iter)->kill_all_tasks();
222+
(*iter)->deref();
224223
}
225224
}
226225

src/rt/rust_scheduler.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ rust_scheduler::rust_scheduler(rust_kernel *kernel,
1111
bool allow_exit,
1212
bool killed,
1313
rust_sched_launcher_factory *launchfac) :
14+
ref_count(1),
1415
kernel(kernel),
1516
live_threads(num_threads),
1617
live_tasks(0),
@@ -22,8 +23,9 @@ rust_scheduler::rust_scheduler(rust_kernel *kernel,
2223
create_task_threads(launchfac, killed);
2324
}
2425

25-
rust_scheduler::~rust_scheduler() {
26+
void rust_scheduler::delete_this() {
2627
destroy_task_threads();
28+
delete this;
2729
}
2830

2931
rust_sched_launcher *

src/rt/rust_scheduler.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,13 @@
1111
#include "rust_globals.h"
1212
#include "util/array_list.h"
1313
#include "rust_kernel.h"
14+
#include "rust_refcount.h"
1415

1516
class rust_sched_launcher;
1617
class rust_sched_launcher_factory;
1718

1819
class rust_scheduler : public kernel_owned<rust_scheduler> {
20+
RUST_ATOMIC_REFCOUNT();
1921
// FIXME (#2693): Make these private
2022
public:
2123
rust_kernel *kernel;
@@ -45,11 +47,13 @@ class rust_scheduler : public kernel_owned<rust_scheduler> {
4547

4648
void exit();
4749

50+
// Called when refcount reaches zero
51+
void delete_this();
52+
4853
public:
4954
rust_scheduler(rust_kernel *kernel, size_t num_threads,
5055
rust_sched_id id, bool allow_exit, bool killed,
5156
rust_sched_launcher_factory *launchfac);
52-
~rust_scheduler();
5357

5458
void start_task_threads();
5559
void join_task_threads();

src/rt/rust_task.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -122,8 +122,6 @@ rust_task_fail(rust_task *task,
122122
struct
123123
rust_task : public kernel_owned<rust_task>
124124
{
125-
// FIXME(#1789) Refcounting no longer seems needed now that tasks don't
126-
// ref their parents. I'll leave it in just in case... -- bblum
127125
RUST_ATOMIC_REFCOUNT();
128126

129127
rust_task_id id;

0 commit comments

Comments
 (0)