From: Matt Helsley This patch uses the task_watcher notifier chain to invoke exit_sem() at appropriate times. Signed-off-by: Matt Helsley Cc: Jes Sorensen Signed-off-by: Andrew Morton --- ipc/sem.c | 23 +++++++++++++++++++++++ kernel/exit.c | 1 - kernel/fork.c | 4 +--- 3 files changed, 24 insertions(+), 4 deletions(-) diff -puN ipc/sem.c~task-watchers-register-semundo-task-watcher ipc/sem.c --- a/ipc/sem.c~task-watchers-register-semundo-task-watcher +++ a/ipc/sem.c @@ -84,6 +84,7 @@ #include #include #include +#include #include #include "util.h" @@ -123,6 +124,27 @@ static int sysvipc_sem_proc_show(struct #define sc_semopm sem_ctls[2] #define sc_semmni sem_ctls[3] +static int sem_undo_task_exit(struct notifier_block *nb, unsigned long val, + void *t) +{ + switch(get_watch_event(val)) { + /* + * If it weren't for the fact that we need clone flags to call + * it we could also implement the copy_semundo portion of + * copy_process inside case WATCH_TASK_INIT + */ + case WATCH_TASK_FREE: + exit_sem(t); + return NOTIFY_OK; + default: /* Don't care */ + return NOTIFY_DONE; + } +} + +static struct notifier_block sem_watch_tasks_nb = { + .notifier_call = sem_undo_task_exit +}; + static void __ipc_init __sem_init_ns(struct ipc_namespace *ns, struct ipc_ids *ids) { ns->ids[IPC_SEM_IDS] = ids; @@ -173,6 +195,7 @@ void __init sem_init (void) ipc_init_proc_interface("sysvipc/sem", " key semid perms nsems uid gid cuid cgid otime ctime\n", IPC_SEM_IDS, sysvipc_sem_proc_show); + register_task_watcher(&sem_watch_tasks_nb); } /* diff -puN kernel/exit.c~task-watchers-register-semundo-task-watcher kernel/exit.c --- a/kernel/exit.c~task-watchers-register-semundo-task-watcher +++ a/kernel/exit.c @@ -915,7 +915,6 @@ fastcall NORET_TYPE void do_exit(long co if (group_dead) acct_process(); - exit_sem(tsk); __exit_files(tsk); __exit_fs(tsk); exit_task_namespaces(tsk); diff -puN kernel/fork.c~task-watchers-register-semundo-task-watcher kernel/fork.c --- a/kernel/fork.c~task-watchers-register-semundo-task-watcher +++ a/kernel/fork.c @@ -1069,7 +1069,7 @@ static task_t *copy_process(unsigned lon if ((retval = copy_semundo(clone_flags, p))) goto bad_fork_cleanup_security; if ((retval = copy_files(clone_flags, p))) - goto bad_fork_cleanup_semundo; + goto bad_fork_cleanup_security; if ((retval = copy_fs(clone_flags, p))) goto bad_fork_cleanup_files; if ((retval = copy_sighand(clone_flags, p))) @@ -1243,8 +1243,6 @@ bad_fork_cleanup_fs: exit_fs(p); /* blocking */ bad_fork_cleanup_files: exit_files(p); /* blocking */ -bad_fork_cleanup_semundo: - exit_sem(p); bad_fork_cleanup_security: security_task_free(p); notify_result = notify_watchers(WATCH_TASK_FREE, p); _