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.