diff --git a/src/system/kernel/image.cpp b/src/system/kernel/image.cpp index 9f3b9b3085..c3bad82ab1 100644 --- a/src/system/kernel/image.cpp +++ b/src/system/kernel/image.cpp @@ -426,20 +426,18 @@ notify_loading_app(status_t result, bool suspend) TeamLocker teamLocker(team); - if (team->loading_info) { + if (team->loading_info != NULL) { // there's indeed someone waiting - struct team_loading_info* loadingInfo = team->loading_info; - team->loading_info = NULL; - - loadingInfo->result = result; - - // we're done with the team stuff, get the scheduler lock instead - teamLocker.Unlock(); thread_prepare_suspend(); // wake up the waiting thread - loadingInfo->condition.NotifyAll(); + team->loading_info->result = result; + team->loading_info->condition.NotifyAll(); + team->loading_info = NULL; + + // we're done with the team stuff + teamLocker.Unlock(); // suspend ourselves, if desired if (suspend) diff --git a/src/system/kernel/team.cpp b/src/system/kernel/team.cpp index 356563a2c8..c08c284a28 100644 --- a/src/system/kernel/team.cpp +++ b/src/system/kernel/team.cpp @@ -1765,11 +1765,13 @@ load_image_internal(char**& _flatArgs, size_t flatArgsSize, int32 argCount, return B_NO_MEMORY; BReference teamReference(team, true); + BReference teamLoadingReference; if ((flags & B_WAIT_TILL_LOADED) != 0) { loadingInfo.condition.Init(team, "image load"); loadingInfo.condition.Add(&loadingWaitEntry); loadingInfo.result = B_ERROR; team->loading_info = &loadingInfo; + teamLoadingReference = teamReference; } // get the parent team @@ -1892,6 +1894,14 @@ load_image_internal(char**& _flatArgs, size_t flatArgsSize, int32 argCount, // responsible for unsetting `loading_info` in the team structure. loadingWaitEntry.Wait(); + // We must synchronize with the thread that woke us up, to ensure + // there are no remaining consumers of the team_loading_info. + team->Lock(); + if (team->loading_info != NULL) + panic("team loading wait complete, but loading_info != NULL"); + team->Unlock(); + teamLoadingReference.Unset(); + if (loadingInfo.result < B_OK) return loadingInfo.result; } @@ -3288,15 +3298,13 @@ team_delete_team(Team* team, port_id debuggerPort) TeamLocker teamLocker(team); - if (team->loading_info) { + if (team->loading_info != NULL) { // there's indeed someone waiting - struct team_loading_info* loadingInfo = team->loading_info; - team->loading_info = NULL; - - loadingInfo->result = B_ERROR; + team->loading_info->result = B_ERROR; // wake up the waiting thread - loadingInfo->condition.NotifyAll(); + team->loading_info->condition.NotifyAll(); + team->loading_info = NULL; } // notify team watchers