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:
@@ -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);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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();
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user