From 6a80e6889ad1f00ec1c8ec1193ff5e346fcd73b7 Mon Sep 17 00:00:00 2001 From: Michael Lotz Date: Fri, 31 Oct 2014 11:58:59 +0100 Subject: [PATCH] kernel: Fix missing reference to team/thread in signal events. The signal to the team/thread is only actually sent in a deferred procedure. To ensure that the team/thread stays valid between the DPC being queued and it actually running, we need to acquire a reference. Fixes #11390, where the DPC was run after the team was already destroyed. --- headers/private/kernel/UserEvent.h | 4 ++++ src/system/kernel/UserEvent.cpp | 30 ++++++++++++++++++++++++++++++ 2 files changed, 34 insertions(+) diff --git a/headers/private/kernel/UserEvent.h b/headers/private/kernel/UserEvent.h index 19a44a366a..081ff9db25 100644 --- a/headers/private/kernel/UserEvent.h +++ b/headers/private/kernel/UserEvent.h @@ -52,6 +52,8 @@ struct TeamSignalEvent : SignalEvent { static TeamSignalEvent* Create(Team* team, uint32 signalNumber, int32 signalCode, int32 errorCode); + virtual status_t Fire(); + protected: virtual void DoDPC(DPCQueue* queue); @@ -69,6 +71,8 @@ struct ThreadSignalEvent : SignalEvent { int32 signalCode, int32 errorCode, pid_t sendingTeam); + virtual status_t Fire(); + protected: virtual void DoDPC(DPCQueue* queue); diff --git a/src/system/kernel/UserEvent.cpp b/src/system/kernel/UserEvent.cpp index a60d230455..2cff40cfb4 100644 --- a/src/system/kernel/UserEvent.cpp +++ b/src/system/kernel/UserEvent.cpp @@ -127,6 +127,20 @@ TeamSignalEvent::Create(Team* team, uint32 signalNumber, int32 signalCode, } +status_t +TeamSignalEvent::Fire() +{ + // We need a reference to the team to guarantee that it is still there when + // the DPC actually runs. + fTeam->AcquireReference(); + status_t result = SignalEvent::Fire(); + if (result != B_OK) + fTeam->ReleaseReference(); + + return result; +} + + void TeamSignalEvent::DoDPC(DPCQueue* queue) { @@ -137,6 +151,7 @@ TeamSignalEvent::DoDPC(DPCQueue* queue) status_t error = send_signal_to_team_locked(fTeam, fSignal->Number(), fSignal, B_DO_NOT_RESCHEDULE); locker.Unlock(); + fTeam->ReleaseReference(); // There are situations (for certain signals), in which // send_signal_to_team_locked() succeeds without queuing the signal. @@ -182,6 +197,20 @@ ThreadSignalEvent::Create(Thread* thread, uint32 signalNumber, int32 signalCode, } +status_t +ThreadSignalEvent::Fire() +{ + // We need a reference to the thread to guarantee that it is still there + // when the DPC actually runs. + fThread->AcquireReference(); + status_t result = SignalEvent::Fire(); + if (result != B_OK) + fThread->ReleaseReference(); + + return result; +} + + void ThreadSignalEvent::DoDPC(DPCQueue* queue) { @@ -193,6 +222,7 @@ ThreadSignalEvent::DoDPC(DPCQueue* queue) fSignal, B_DO_NOT_RESCHEDULE); locker.Unlock(); teamLocker.Unlock(); + fThread->ReleaseReference(); // There are situations (for certain signals), in which // send_signal_to_team_locked() succeeds without queuing the signal.