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.
This commit is contained in:
parent
6109f53bc6
commit
6a80e6889a
@ -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);
|
||||
|
||||
|
@ -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.
|
||||
|
Loading…
x
Reference in New Issue
Block a user