Make more robust with respect on invalid input data
* When encountering scheduling data referring to an unknown thread, add a dummy thread for it. This prevents a crash when processing the per-thread events later. * Make warning output more uniform. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@43214 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -890,7 +890,7 @@ ModelLoader::_HandleTeamRemoved(system_profiler_team_removed* event)
|
|||||||
if (Model::Team* team = fModel->TeamByID(event->team))
|
if (Model::Team* team = fModel->TeamByID(event->team))
|
||||||
team->SetDeletionTime(fState->LastEventTime());
|
team->SetDeletionTime(fState->LastEventTime());
|
||||||
else
|
else
|
||||||
printf("Removed event for unknown team: %ld\n", event->team);
|
printf("Warning: Removed event for unknown team: %ld\n", event->team);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -904,11 +904,7 @@ ModelLoader::_HandleTeamExec(system_profiler_team_exec* event)
|
|||||||
void
|
void
|
||||||
ModelLoader::_HandleThreadAdded(system_profiler_thread_added* event)
|
ModelLoader::_HandleThreadAdded(system_profiler_thread_added* event)
|
||||||
{
|
{
|
||||||
ExtendedThreadSchedulingState* thread = _AddThread(event);
|
_AddThread(event)->IncrementEventCount();
|
||||||
if (thread == NULL)
|
|
||||||
throw std::bad_alloc();
|
|
||||||
|
|
||||||
thread->IncrementEventCount();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -916,11 +912,14 @@ void
|
|||||||
ModelLoader::_HandleThreadRemoved(system_profiler_thread_removed* event)
|
ModelLoader::_HandleThreadRemoved(system_profiler_thread_removed* event)
|
||||||
{
|
{
|
||||||
ExtendedThreadSchedulingState* thread = fState->LookupThread(event->thread);
|
ExtendedThreadSchedulingState* thread = fState->LookupThread(event->thread);
|
||||||
if (thread != NULL) {
|
if (thread == NULL) {
|
||||||
thread->thread->SetDeletionTime(fState->LastEventTime());
|
printf("Warning: Removed event for unknown thread: %ld\n",
|
||||||
thread->IncrementEventCount();
|
event->thread);
|
||||||
} else
|
thread = _AddUnknownThread(event->thread);
|
||||||
printf("Removed event for unknown team: %ld\n", event->thread);
|
}
|
||||||
|
|
||||||
|
thread->thread->SetDeletionTime(fState->LastEventTime());
|
||||||
|
thread->IncrementEventCount();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -932,7 +931,9 @@ ModelLoader::_HandleThreadScheduled(uint32 cpu,
|
|||||||
|
|
||||||
ExtendedThreadSchedulingState* thread = fState->LookupThread(event->thread);
|
ExtendedThreadSchedulingState* thread = fState->LookupThread(event->thread);
|
||||||
if (thread == NULL) {
|
if (thread == NULL) {
|
||||||
printf("Schedule event for unknown thread: %ld\n", event->thread);
|
printf("Warning: Schedule event for unknown thread: %ld\n",
|
||||||
|
event->thread);
|
||||||
|
thread = _AddUnknownThread(event->thread);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -965,9 +966,9 @@ ModelLoader::_HandleThreadScheduled(uint32 cpu,
|
|||||||
|
|
||||||
thread = fState->LookupThread(event->previous_thread);
|
thread = fState->LookupThread(event->previous_thread);
|
||||||
if (thread == NULL) {
|
if (thread == NULL) {
|
||||||
printf("Schedule event for unknown previous thread: %ld\n",
|
printf("Warning: Schedule event for unknown previous thread: %ld\n",
|
||||||
event->previous_thread);
|
event->previous_thread);
|
||||||
return;
|
thread = _AddUnknownThread(event->previous_thread);
|
||||||
}
|
}
|
||||||
|
|
||||||
diffTime = fState->LastEventTime() - thread->lastTime;
|
diffTime = fState->LastEventTime() - thread->lastTime;
|
||||||
@@ -1034,9 +1035,9 @@ ModelLoader::_HandleThreadEnqueuedInRunQueue(
|
|||||||
|
|
||||||
ExtendedThreadSchedulingState* thread = fState->LookupThread(event->thread);
|
ExtendedThreadSchedulingState* thread = fState->LookupThread(event->thread);
|
||||||
if (thread == NULL) {
|
if (thread == NULL) {
|
||||||
printf("Enqueued in run queue event for unknown thread: %ld\n",
|
printf("Warning: Enqueued in run queue event for unknown thread: %ld\n",
|
||||||
event->thread);
|
event->thread);
|
||||||
return;
|
thread = _AddUnknownThread(event->thread);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (thread->state == RUNNING || thread->state == STILL_RUNNING) {
|
if (thread->state == RUNNING || thread->state == STILL_RUNNING) {
|
||||||
@@ -1071,9 +1072,9 @@ ModelLoader::_HandleThreadRemovedFromRunQueue(uint32 cpu,
|
|||||||
|
|
||||||
ExtendedThreadSchedulingState* thread = fState->LookupThread(event->thread);
|
ExtendedThreadSchedulingState* thread = fState->LookupThread(event->thread);
|
||||||
if (thread == NULL) {
|
if (thread == NULL) {
|
||||||
printf("Removed from run queue event for unknown thread: %ld\n",
|
printf("Warning: Removed from run queue event for unknown thread: "
|
||||||
event->thread);
|
"%ld\n", event->thread);
|
||||||
return;
|
thread = _AddUnknownThread(event->thread);
|
||||||
}
|
}
|
||||||
|
|
||||||
// This really only happens when the thread priority is changed
|
// This really only happens when the thread priority is changed
|
||||||
@@ -1111,7 +1112,7 @@ ModelLoader::_HandleIOSchedulerAdded(system_profiler_io_scheduler_added* event)
|
|||||||
{
|
{
|
||||||
Model::IOScheduler* scheduler = fModel->IOSchedulerByID(event->scheduler);
|
Model::IOScheduler* scheduler = fModel->IOSchedulerByID(event->scheduler);
|
||||||
if (scheduler != NULL) {
|
if (scheduler != NULL) {
|
||||||
printf("Duplicate added event for I/O scheduler %ld\n",
|
printf("Warning: Duplicate added event for I/O scheduler %ld\n",
|
||||||
event->scheduler);
|
event->scheduler);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -1126,18 +1127,21 @@ ModelLoader::_HandleIORequestScheduled(io_request_scheduled* event)
|
|||||||
{
|
{
|
||||||
IORequest* request = fIORequests->Lookup(event->request);
|
IORequest* request = fIORequests->Lookup(event->request);
|
||||||
if (request != NULL) {
|
if (request != NULL) {
|
||||||
printf("Duplicate schedule event for I/O request %p\n", event->request);
|
printf("Warning: Duplicate schedule event for I/O request %p\n",
|
||||||
|
event->request);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
ExtendedThreadSchedulingState* thread = fState->LookupThread(event->thread);
|
ExtendedThreadSchedulingState* thread = fState->LookupThread(event->thread);
|
||||||
if (thread == NULL) {
|
if (thread == NULL) {
|
||||||
printf("I/O request for unknown thread %ld\n", event->thread);
|
printf("Warning: I/O request for unknown thread %ld\n", event->thread);
|
||||||
return;
|
thread = _AddUnknownThread(event->thread);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fModel->IOSchedulerByID(event->scheduler) == NULL) {
|
if (fModel->IOSchedulerByID(event->scheduler) == NULL) {
|
||||||
printf("I/O requests for unknown scheduler %ld\n", event->scheduler);
|
printf("Warning: I/O requests for unknown scheduler %ld\n",
|
||||||
|
event->scheduler);
|
||||||
|
// TODO: Add state for unknown scheduler, as we do for threads.
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1170,7 +1174,7 @@ ModelLoader::_HandleIOOperationStarted(io_operation_started* event)
|
|||||||
{
|
{
|
||||||
IORequest* request = fIORequests->Lookup(event->request);
|
IORequest* request = fIORequests->Lookup(event->request);
|
||||||
if (request == NULL) {
|
if (request == NULL) {
|
||||||
printf("ModelLoader::_HandleIOOperationStarted(): I/O request for operation %p not found\n",
|
printf("Warning: I/O request for operation %p not found\n",
|
||||||
event->operation);
|
event->operation);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -1188,15 +1192,14 @@ ModelLoader::_HandleIOOperationFinished(io_operation_finished* event)
|
|||||||
{
|
{
|
||||||
IORequest* request = fIORequests->Lookup(event->request);
|
IORequest* request = fIORequests->Lookup(event->request);
|
||||||
if (request == NULL) {
|
if (request == NULL) {
|
||||||
printf("ModelLoader::_HandleIOOperationFinished(): I/O request for "
|
printf("Warning: I/O request for operation %p not found\n",
|
||||||
"operation %p not found\n", event->operation);
|
event->operation);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
IOOperation* operation = request->FindOperation(event->operation);
|
IOOperation* operation = request->FindOperation(event->operation);
|
||||||
if (operation == NULL) {
|
if (operation == NULL) {
|
||||||
printf("ModelLoader::_HandleIOOperationFinished(): operation %p not "
|
printf("Warning: operation %p not found\n", event->operation);
|
||||||
"found\n", event->operation);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1210,19 +1213,20 @@ ModelLoader::_AddThread(system_profiler_thread_added* event)
|
|||||||
// do we know the thread already?
|
// do we know the thread already?
|
||||||
ExtendedThreadSchedulingState* info = fState->LookupThread(event->thread);
|
ExtendedThreadSchedulingState* info = fState->LookupThread(event->thread);
|
||||||
if (info != NULL) {
|
if (info != NULL) {
|
||||||
// TODO: ?
|
printf("Warning: Duplicate thread added event for thread %" B_PRId32
|
||||||
|
"\n", event->thread);
|
||||||
return info;
|
return info;
|
||||||
}
|
}
|
||||||
|
|
||||||
// add the thread to the model
|
// add the thread to the model
|
||||||
Model::Thread* thread = fModel->AddThread(event, fState->LastEventTime());
|
Model::Thread* thread = fModel->AddThread(event, fState->LastEventTime());
|
||||||
if (thread == NULL)
|
if (thread == NULL)
|
||||||
return NULL;
|
throw std::bad_alloc();
|
||||||
|
|
||||||
// create and add a ThreadSchedulingState
|
// create and add a ThreadSchedulingState
|
||||||
info = new(std::nothrow) ExtendedThreadSchedulingState(thread);
|
info = new(std::nothrow) ExtendedThreadSchedulingState(thread);
|
||||||
if (info == NULL)
|
if (info == NULL)
|
||||||
return NULL;
|
throw std::bad_alloc();
|
||||||
|
|
||||||
// TODO: The priority is missing from the system_profiler_thread_added
|
// TODO: The priority is missing from the system_profiler_thread_added
|
||||||
// struct. For now guess at least whether this is an idle thread.
|
// struct. For now guess at least whether this is an idle thread.
|
||||||
@@ -1237,6 +1241,64 @@ ModelLoader::_AddThread(system_profiler_thread_added* event)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
ModelLoader::ExtendedThreadSchedulingState*
|
||||||
|
ModelLoader::_AddUnknownThread(thread_id threadID)
|
||||||
|
{
|
||||||
|
// create a dummy "add thread" event
|
||||||
|
system_profiler_thread_added* event = (system_profiler_thread_added*)
|
||||||
|
malloc(sizeof(system_profiler_thread_added));
|
||||||
|
if (event == NULL)
|
||||||
|
throw std::bad_alloc();
|
||||||
|
|
||||||
|
if (!fModel->AddAssociatedData(event)) {
|
||||||
|
free(event);
|
||||||
|
throw std::bad_alloc();
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
event->team = _AddUnknownTeam()->ID();
|
||||||
|
event->thread = threadID;
|
||||||
|
snprintf(event->name, sizeof(event->name), "unknown thread %" B_PRId32,
|
||||||
|
threadID);
|
||||||
|
|
||||||
|
// add the thread to the model
|
||||||
|
ExtendedThreadSchedulingState* state = _AddThread(event);
|
||||||
|
return state;
|
||||||
|
} catch (...) {
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Model::Team*
|
||||||
|
ModelLoader::_AddUnknownTeam()
|
||||||
|
{
|
||||||
|
team_id teamID = 0;
|
||||||
|
Model::Team* team = fModel->TeamByID(teamID);
|
||||||
|
if (team != NULL)
|
||||||
|
return team;
|
||||||
|
|
||||||
|
// create a dummy "add team" event
|
||||||
|
static const char* const kUnknownThreadsTeamName = "unknown threads";
|
||||||
|
size_t nameLength = strlen(kUnknownThreadsTeamName);
|
||||||
|
|
||||||
|
system_profiler_team_added* event = (system_profiler_team_added*)
|
||||||
|
malloc(sizeof(system_profiler_team_added) + nameLength);
|
||||||
|
if (event == NULL)
|
||||||
|
throw std::bad_alloc();
|
||||||
|
|
||||||
|
event->team = teamID;
|
||||||
|
event->args_offset = nameLength;
|
||||||
|
strlcpy(event->name, kUnknownThreadsTeamName, nameLength + 1);
|
||||||
|
|
||||||
|
// add the team to the model
|
||||||
|
team = fModel->AddTeam(event, fState->LastEventTime());
|
||||||
|
if (team == NULL)
|
||||||
|
throw std::bad_alloc();
|
||||||
|
|
||||||
|
return team;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
ModelLoader::_AddThreadWaitObject(ExtendedThreadSchedulingState* thread,
|
ModelLoader::_AddThreadWaitObject(ExtendedThreadSchedulingState* thread,
|
||||||
uint32 type, addr_t object)
|
uint32 type, addr_t object)
|
||||||
|
|||||||
@@ -106,6 +106,10 @@ private:
|
|||||||
|
|
||||||
ExtendedThreadSchedulingState* _AddThread(
|
ExtendedThreadSchedulingState* _AddThread(
|
||||||
system_profiler_thread_added* event);
|
system_profiler_thread_added* event);
|
||||||
|
ExtendedThreadSchedulingState* _AddUnknownThread(
|
||||||
|
thread_id threadID);
|
||||||
|
Model::Team* _AddUnknownTeam();
|
||||||
|
|
||||||
void _AddThreadWaitObject(
|
void _AddThreadWaitObject(
|
||||||
ExtendedThreadSchedulingState* thread,
|
ExtendedThreadSchedulingState* thread,
|
||||||
uint32 type, addr_t object);
|
uint32 type, addr_t object);
|
||||||
|
|||||||
Reference in New Issue
Block a user