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:
@@ -52,6 +52,8 @@ struct TeamSignalEvent : SignalEvent {
|
|||||||
static TeamSignalEvent* Create(Team* team, uint32 signalNumber,
|
static TeamSignalEvent* Create(Team* team, uint32 signalNumber,
|
||||||
int32 signalCode, int32 errorCode);
|
int32 signalCode, int32 errorCode);
|
||||||
|
|
||||||
|
virtual status_t Fire();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual void DoDPC(DPCQueue* queue);
|
virtual void DoDPC(DPCQueue* queue);
|
||||||
|
|
||||||
@@ -69,6 +71,8 @@ struct ThreadSignalEvent : SignalEvent {
|
|||||||
int32 signalCode, int32 errorCode,
|
int32 signalCode, int32 errorCode,
|
||||||
pid_t sendingTeam);
|
pid_t sendingTeam);
|
||||||
|
|
||||||
|
virtual status_t Fire();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual void DoDPC(DPCQueue* queue);
|
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
|
void
|
||||||
TeamSignalEvent::DoDPC(DPCQueue* queue)
|
TeamSignalEvent::DoDPC(DPCQueue* queue)
|
||||||
{
|
{
|
||||||
@@ -137,6 +151,7 @@ TeamSignalEvent::DoDPC(DPCQueue* queue)
|
|||||||
status_t error = send_signal_to_team_locked(fTeam, fSignal->Number(),
|
status_t error = send_signal_to_team_locked(fTeam, fSignal->Number(),
|
||||||
fSignal, B_DO_NOT_RESCHEDULE);
|
fSignal, B_DO_NOT_RESCHEDULE);
|
||||||
locker.Unlock();
|
locker.Unlock();
|
||||||
|
fTeam->ReleaseReference();
|
||||||
|
|
||||||
// There are situations (for certain signals), in which
|
// There are situations (for certain signals), in which
|
||||||
// send_signal_to_team_locked() succeeds without queuing the signal.
|
// 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
|
void
|
||||||
ThreadSignalEvent::DoDPC(DPCQueue* queue)
|
ThreadSignalEvent::DoDPC(DPCQueue* queue)
|
||||||
{
|
{
|
||||||
@@ -193,6 +222,7 @@ ThreadSignalEvent::DoDPC(DPCQueue* queue)
|
|||||||
fSignal, B_DO_NOT_RESCHEDULE);
|
fSignal, B_DO_NOT_RESCHEDULE);
|
||||||
locker.Unlock();
|
locker.Unlock();
|
||||||
teamLocker.Unlock();
|
teamLocker.Unlock();
|
||||||
|
fThread->ReleaseReference();
|
||||||
|
|
||||||
// There are situations (for certain signals), in which
|
// There are situations (for certain signals), in which
|
||||||
// send_signal_to_team_locked() succeeds without queuing the signal.
|
// send_signal_to_team_locked() succeeds without queuing the signal.
|
||||||
|
|||||||
Reference in New Issue
Block a user