Fix thread status race-condition caused by hold_thread() in do_kill() and terminate()

Conflicts:
	arch/x86_64/kernel/syscall.c
	kernel/syscall.c
This commit is contained in:
Masamichi Takagi
2018-01-26 22:00:24 +09:00
parent 51bc5fd61f
commit 65667709a8
4 changed files with 25 additions and 20 deletions

View File

@@ -1329,15 +1329,20 @@ done:
mcs_rwlock_reader_lock_noirq(&tproc->update_lock, &updatelock); mcs_rwlock_reader_lock_noirq(&tproc->update_lock, &updatelock);
savelock = &tthread->sigpendinglock; savelock = &tthread->sigpendinglock;
head = &tthread->sigpending; head = &tthread->sigpending;
if(sig == SIGKILL || mcs_rwlock_reader_lock_noirq(&tproc->threads_lock, &lock);
(tproc->status != PS_EXITED && if (tthread->status != PS_EXITED &&
tproc->status != PS_ZOMBIE && (sig == SIGKILL ||
tthread->status != PS_EXITED)){ (tproc->status != PS_EXITED && tproc->status != PS_ZOMBIE))) {
hold_thread(tthread); hold_thread(tthread);
if ((rc = hold_thread(tthread))) {
kprintf("%s: ERROR hold_thread returned %d,tid=%d\n", __FUNCTION__, rc, tthread->tid);
tthread = NULL;
}
} }
else{ else{
tthread = NULL; tthread = NULL;
} }
mcs_rwlock_reader_unlock_noirq(&tproc->threads_lock, &lock);
mcs_rwlock_reader_unlock_noirq(&tproc->update_lock, &updatelock); mcs_rwlock_reader_unlock_noirq(&tproc->update_lock, &updatelock);
mcs_rwlock_reader_unlock_noirq(&thash->lock[hash], &lock); mcs_rwlock_reader_unlock_noirq(&thash->lock[hash], &lock);
} }

View File

@@ -575,9 +575,6 @@ struct process {
int nr_processes; /* For partitioned execution */ int nr_processes; /* For partitioned execution */
}; };
void hold_thread(struct thread *ftn);
void release_thread(struct thread *ftn);
/* /*
* Scheduling policies * Scheduling policies
*/ */
@@ -753,7 +750,7 @@ struct thread *create_thread(unsigned long user_pc,
struct thread *clone_thread(struct thread *org, unsigned long pc, struct thread *clone_thread(struct thread *org, unsigned long pc,
unsigned long sp, int clone_flags); unsigned long sp, int clone_flags);
void destroy_thread(struct thread *thread); void destroy_thread(struct thread *thread);
void hold_thread(struct thread *thread); int hold_thread(struct thread *thread);
void release_thread(struct thread *thread); void release_thread(struct thread *thread);
void flush_process_memory(struct process_vm *vm); void flush_process_memory(struct process_vm *vm);
void hold_process_vm(struct process_vm *vm); void hold_process_vm(struct process_vm *vm);

View File

@@ -2571,14 +2571,15 @@ out:
return error; return error;
} }
void hold_thread(struct thread *thread) int hold_thread(struct thread *thread)
{ {
if (thread->status == PS_EXITED) { if (thread->status == PS_EXITED) {
panic("hold_thread: already exited process"); kprintf("hold_thread: ERROR: already exited process,tid=%d\n", thread->tid);
return -ESRCH;
} }
ihk_atomic_inc(&thread->refcount); ihk_atomic_inc(&thread->refcount);
return; return 0;
} }
void void

View File

@@ -1004,13 +1004,13 @@ void terminate(int rc, int sig)
sync_child_event(proc->monitoring_event); sync_child_event(proc->monitoring_event);
// clean up threads // clean up threads
mcs_rwlock_reader_lock(&proc->threads_lock, &lock); // conflict clone mcs_rwlock_writer_lock(&proc->threads_lock, &lock); // conflict clone
mcs_rwlock_writer_lock_noirq(&proc->update_lock, &updatelock); mcs_rwlock_writer_lock_noirq(&proc->update_lock, &updatelock);
if (proc->status == PS_EXITED) { if (proc->status == PS_EXITED) {
mcs_rwlock_writer_unlock_noirq(&proc->update_lock, &updatelock);
mcs_rwlock_reader_unlock(&proc->threads_lock, &lock);
preempt_disable(); preempt_disable();
mythread->status = PS_EXITED; mythread->status = PS_EXITED;
mcs_rwlock_writer_unlock_noirq(&proc->update_lock, &updatelock);
mcs_rwlock_writer_unlock(&proc->threads_lock, &lock);
release_thread(mythread); release_thread(mythread);
preempt_enable(); preempt_enable();
schedule(); schedule();
@@ -1021,10 +1021,10 @@ void terminate(int rc, int sig)
exit_status = ((rc & 0x00ff) << 8) | (sig & 0xff); exit_status = ((rc & 0x00ff) << 8) | (sig & 0xff);
mythread->exit_status = exit_status; mythread->exit_status = exit_status;
proc->status = PS_EXITED; proc->status = PS_EXITED;
terminate_mcexec(rc, sig);
mcs_rwlock_writer_unlock_noirq(&proc->update_lock, &updatelock); mcs_rwlock_writer_unlock_noirq(&proc->update_lock, &updatelock);
mcs_rwlock_reader_unlock(&proc->threads_lock, &lock); mcs_rwlock_writer_unlock(&proc->threads_lock, &lock);
terminate_mcexec(rc, sig);
mcs_rwlock_writer_lock(&proc->threads_lock, &lock); mcs_rwlock_writer_lock(&proc->threads_lock, &lock);
list_del(&mythread->siblings_list); list_del(&mythread->siblings_list);
@@ -1174,7 +1174,9 @@ void terminate(int rc, int sig)
finalize_process(proc); finalize_process(proc);
preempt_disable(); preempt_disable();
mcs_rwlock_writer_lock(&proc->threads_lock, &lock);
mythread->status = PS_EXITED; mythread->status = PS_EXITED;
mcs_rwlock_writer_unlock(&proc->threads_lock, &lock);
release_thread(mythread); release_thread(mythread);
release_process_vm(vm); release_process_vm(vm);
preempt_enable(); preempt_enable();
@@ -5475,16 +5477,16 @@ do_exit(int code)
FUTEX_WAKE, 1, 0, NULL, 0, 0, 1); FUTEX_WAKE, 1, 0, NULL, 0, 0, 1);
} }
mcs_rwlock_reader_lock(&proc->threads_lock, &lock); mcs_rwlock_writer_lock(&proc->threads_lock, &lock);
if(proc->status == PS_EXITED){ if(proc->status == PS_EXITED){
mcs_rwlock_reader_unlock(&proc->threads_lock, &lock); mcs_rwlock_writer_unlock(&proc->threads_lock, &lock);
terminate(exit_status, 0); terminate(exit_status, 0);
return; return;
} }
preempt_disable(); preempt_disable();
thread->status = PS_EXITED; thread->status = PS_EXITED;
sync_child_event(thread->proc->monitoring_event); sync_child_event(thread->proc->monitoring_event);
mcs_rwlock_reader_unlock(&proc->threads_lock, &lock); mcs_rwlock_writer_unlock(&proc->threads_lock, &lock);
release_thread(thread); release_thread(thread);
preempt_enable(); preempt_enable();