Ok; so I think this matches what you were suggested. We unsubscribe the
subscriber that knows about the failure. For other subscribers, they now
get cleaned up in copy_process when the fork fails.
The changes to __pnotify_fork are just comment changes.
I'll run some tests against this but my tests won't catch this type of
thing, at least not yet.
diff -Narup -x linux/.pc linux-orig/kernel/fork.c linux/kernel/fork.c
--- linux-orig/kernel/fork.c 2005-10-04 09:01:09.105780000 -0500
+++ linux/kernel/fork.c 2005-10-04 09:19:14.548775980 -0500
@@ -1086,7 +1086,7 @@ static task_t *copy_process(unsigned lon
if (sigismember(¤t->pending.signal, SIGKILL)) {
write_unlock_irq(&tasklist_lock);
retval = -EINTR;
- goto bad_fork_cleanup_pnotify;
+ goto bad_fork_cleanup_namespace;
}
/* CLONE_PARENT re-uses the old parent */
@@ -1172,9 +1172,8 @@ fork_out:
return ERR_PTR(retval);
return p;
-bad_fork_cleanup_pnotify:
- pnotify_exit(p);
bad_fork_cleanup_namespace:
+ pnotify_exit(p);
exit_namespace(p);
bad_fork_cleanup_keys:
exit_keys(p);
diff -Narup -x linux/.pc linux-orig/kernel/pnotify.c linux/kernel/pnotify.c
--- linux-orig/kernel/pnotify.c 2005-09-30 16:05:56.548237000 -0500
+++ linux/kernel/pnotify.c 2005-10-04 09:22:02.585499338 -0500
@@ -458,10 +458,10 @@ __pnotify_fork(struct task_struct *to_ta
from_subscriber->events);
if (!to_subscriber) {
/* Failed to get memory.
- * we don't force __pnotify_exit to run here because
- * the child is in-consturction and not running yet.
* We don't need a write lock on the subscriber
* list because the child is in construction.
+ * pnotify_exit is run in copy_process for failed
+ * forks and will clean up the other subscribers.
*/
pnotify_unsubscribe(to_task);
up_read(&from_task->pnotify_subscriber_list_sem);
@@ -474,8 +474,8 @@ __pnotify_fork(struct task_struct *to_ta
/* Propagates to copy_process as a fork failure.
* Since the child is in consturction, we don't
* need a write lock on the subscriber list.
- * __pnotify_exit isn't run because the child
- * never got running, exit doesn't make sense.
+ * pnotify_exit is run in copy_process for failed
+ * forks and will clean up the other subscribers.
*/
pnotify_unsubscribe(to_task);
up_read(&from_task->pnotify_subscriber_list_sem);
|