diff --git a/headers/private/kernel/team.h b/headers/private/kernel/team.h index 9f51e9f673..4b1567f492 100644 --- a/headers/private/kernel/team.h +++ b/headers/private/kernel/team.h @@ -20,6 +20,7 @@ team_id team_create_team(const char *path, const char *name, char **args, int ar status_t wait_for_team(team_id id, status_t *returnCode); void team_remove_team(struct team *team, struct process_group **_freeGroup); void team_delete_team(struct team *team); +struct process_group *team_get_process_group_locked(struct team *team, pid_t id); void team_delete_process_group(struct process_group *group); struct team *team_get_kernel_team(void); team_id team_get_kernel_team_id(void); diff --git a/src/system/kernel/signal.c b/src/system/kernel/signal.c index fd5f9e2611..bd2b89a0ba 100644 --- a/src/system/kernel/signal.c +++ b/src/system/kernel/signal.c @@ -290,11 +290,6 @@ send_signal_etc(pid_t id, uint signal, uint32 flags) if (signal < 0 || signal > MAX_SIGNO) return B_BAD_VALUE; - if (id == 0) { - // send a signal to the current team - id = thread_get_current_thread()->team->main_thread->id; - } - state = disable_interrupts(); if (id > 0) { @@ -309,23 +304,25 @@ send_signal_etc(pid_t id, uint signal, uint32 flags) // send a signal to the specified process group // (the absolute value of the id) - GRAB_THREAD_LOCK(); + struct team *team = thread_get_current_thread()->team; + struct process_group *group; - thread = thread_get_thread_struct_locked(-id); - if (thread != NULL) { - struct process_group *group; + // TODO: handle -1 correctly + if (id == 0 || id == -1) { + // send a signal to the current team + id = thread_get_current_thread()->team->main_thread->id; + } else + id = -id; + + GRAB_TEAM_LOCK(); + + group = team_get_process_group_locked(team, id); + if (group != NULL) { struct team *team, *next; // we need a safe way to get from the thread to the process group id = thread->team->id; - RELEASE_THREAD_LOCK(); - GRAB_TEAM_LOCK(); - - // get a pointer to the process group - team = team_get_team_struct_locked(id); - group = team->group; - for (team = group->teams; team != NULL; team = next) { next = team->group_next; id = team->main_thread->id; @@ -342,9 +339,9 @@ send_signal_etc(pid_t id, uint signal, uint32 flags) RELEASE_THREAD_LOCK(); } - RELEASE_TEAM_LOCK(); - GRAB_THREAD_LOCK(); } + RELEASE_TEAM_LOCK(); + GRAB_THREAD_LOCK(); } // ToDo: maybe the scheduler should only be invoked if there is reason to do it? diff --git a/src/system/kernel/team.c b/src/system/kernel/team.c index bd576cc3bd..9bb69dd86c 100644 --- a/src/system/kernel/team.c +++ b/src/system/kernel/team.c @@ -1213,25 +1213,6 @@ err1: } -/** This searches the session of the team for the specified group ID. - * You must hold the team lock when you call this function. - */ - -static struct process_group * -get_process_group_locked(struct team *team, pid_t id) -{ - struct process_group *group; - struct team_key key; - key.id = id; - - group = (struct process_group *)hash_lookup(sGroupHash, &key); - if (group != NULL && team->group->session == group->session) - return group; - - return NULL; -} - - static status_t update_wait_for_any(struct team *team, thread_id child, int32 change) { @@ -1252,7 +1233,7 @@ update_wait_for_any(struct team *team, thread_id child, int32 change) if (child < 0) { // we wait for all children of the specified process group - group = get_process_group_locked(team, -child); + group = team_get_process_group_locked(team, -child); } else { // we wait for any children of the current team's group group = team->group; @@ -1337,7 +1318,7 @@ get_death_entry(struct team *team, pid_t child, struct death_entry *death, return get_team_death_entry(team, child, death, _freeDeath); } else if (child < 0) { // we wait for all children of the specified process group - group = get_process_group_locked(team, -child); + group = team_get_process_group_locked(team, -child); if (group == NULL) return B_BAD_THREAD_ID; } else { @@ -1570,6 +1551,25 @@ team_get_team_struct_locked(team_id id) } +/** This searches the session of the team for the specified group ID. + * You must hold the team lock when you call this function. + */ + +struct process_group * +team_get_process_group_locked(struct team *team, pid_t id) +{ + struct process_group *group; + struct team_key key; + key.id = id; + + group = (struct process_group *)hash_lookup(sGroupHash, &key); + if (group != NULL && team->group->session == group->session) + return group; + + return NULL; +} + + void team_delete_process_group(struct process_group *group) { @@ -2358,7 +2358,7 @@ _user_setpgid(pid_t processID, pid_t groupID) // check if this team can have the group ID; there must be one matching // process ID in the team's session - struct process_group *group = get_process_group_locked(team, groupID); + struct process_group *group = team_get_process_group_locked(team, groupID); if (group) { // we got a group, let's move the team there remove_team_from_group(team, &freeGroup);