diff options
-rw-r--r-- | fs/eventpoll.c | 4 | ||||
-rw-r--r-- | fs/signalfd.c | 11 | ||||
-rw-r--r-- | include/asm-generic/poll.h | 2 | ||||
-rw-r--r-- | include/linux/signalfd.h | 5 | ||||
-rw-r--r-- | kernel/fork.c | 5 |
5 files changed, 25 insertions, 2 deletions
diff --git a/fs/eventpoll.c b/fs/eventpoll.c index aabdfc38cf24..34bbfc6dd8dc 100644 --- a/fs/eventpoll.c +++ b/fs/eventpoll.c | |||
@@ -842,6 +842,10 @@ static int ep_poll_callback(wait_queue_t *wait, unsigned mode, int sync, void *k | |||
842 | struct epitem *epi = ep_item_from_wait(wait); | 842 | struct epitem *epi = ep_item_from_wait(wait); |
843 | struct eventpoll *ep = epi->ep; | 843 | struct eventpoll *ep = epi->ep; |
844 | 844 | ||
845 | /* the caller holds eppoll_entry->whead->lock */ | ||
846 | if ((unsigned long)key & POLLFREE) | ||
847 | list_del_init(&wait->task_list); | ||
848 | |||
845 | spin_lock_irqsave(&ep->lock, flags); | 849 | spin_lock_irqsave(&ep->lock, flags); |
846 | 850 | ||
847 | /* | 851 | /* |
diff --git a/fs/signalfd.c b/fs/signalfd.c index 492465b451dd..79c1eea98a3a 100644 --- a/fs/signalfd.c +++ b/fs/signalfd.c | |||
@@ -30,6 +30,17 @@ | |||
30 | #include <linux/signalfd.h> | 30 | #include <linux/signalfd.h> |
31 | #include <linux/syscalls.h> | 31 | #include <linux/syscalls.h> |
32 | 32 | ||
33 | void signalfd_cleanup(struct sighand_struct *sighand) | ||
34 | { | ||
35 | wait_queue_head_t *wqh = &sighand->signalfd_wqh; | ||
36 | |||
37 | if (likely(!waitqueue_active(wqh))) | ||
38 | return; | ||
39 | |||
40 | /* wait_queue_t->func(POLLFREE) should do remove_wait_queue() */ | ||
41 | wake_up_poll(wqh, POLLHUP | POLLFREE); | ||
42 | } | ||
43 | |||
33 | struct signalfd_ctx { | 44 | struct signalfd_ctx { |
34 | sigset_t sigmask; | 45 | sigset_t sigmask; |
35 | }; | 46 | }; |
diff --git a/include/asm-generic/poll.h b/include/asm-generic/poll.h index 44bce836d350..9ce7f44aebd2 100644 --- a/include/asm-generic/poll.h +++ b/include/asm-generic/poll.h | |||
@@ -28,6 +28,8 @@ | |||
28 | #define POLLRDHUP 0x2000 | 28 | #define POLLRDHUP 0x2000 |
29 | #endif | 29 | #endif |
30 | 30 | ||
31 | #define POLLFREE 0x4000 /* currently only for epoll */ | ||
32 | |||
31 | struct pollfd { | 33 | struct pollfd { |
32 | int fd; | 34 | int fd; |
33 | short events; | 35 | short events; |
diff --git a/include/linux/signalfd.h b/include/linux/signalfd.h index 3ff4961da9b5..247399b2979a 100644 --- a/include/linux/signalfd.h +++ b/include/linux/signalfd.h | |||
@@ -61,13 +61,16 @@ static inline void signalfd_notify(struct task_struct *tsk, int sig) | |||
61 | wake_up(&tsk->sighand->signalfd_wqh); | 61 | wake_up(&tsk->sighand->signalfd_wqh); |
62 | } | 62 | } |
63 | 63 | ||
64 | extern void signalfd_cleanup(struct sighand_struct *sighand); | ||
65 | |||
64 | #else /* CONFIG_SIGNALFD */ | 66 | #else /* CONFIG_SIGNALFD */ |
65 | 67 | ||
66 | static inline void signalfd_notify(struct task_struct *tsk, int sig) { } | 68 | static inline void signalfd_notify(struct task_struct *tsk, int sig) { } |
67 | 69 | ||
70 | static inline void signalfd_cleanup(struct sighand_struct *sighand) { } | ||
71 | |||
68 | #endif /* CONFIG_SIGNALFD */ | 72 | #endif /* CONFIG_SIGNALFD */ |
69 | 73 | ||
70 | #endif /* __KERNEL__ */ | 74 | #endif /* __KERNEL__ */ |
71 | 75 | ||
72 | #endif /* _LINUX_SIGNALFD_H */ | 76 | #endif /* _LINUX_SIGNALFD_H */ |
73 | |||
diff --git a/kernel/fork.c b/kernel/fork.c index b77fd559c78e..e2cd3e2a5ae8 100644 --- a/kernel/fork.c +++ b/kernel/fork.c | |||
@@ -66,6 +66,7 @@ | |||
66 | #include <linux/user-return-notifier.h> | 66 | #include <linux/user-return-notifier.h> |
67 | #include <linux/oom.h> | 67 | #include <linux/oom.h> |
68 | #include <linux/khugepaged.h> | 68 | #include <linux/khugepaged.h> |
69 | #include <linux/signalfd.h> | ||
69 | 70 | ||
70 | #include <asm/pgtable.h> | 71 | #include <asm/pgtable.h> |
71 | #include <asm/pgalloc.h> | 72 | #include <asm/pgalloc.h> |
@@ -935,8 +936,10 @@ static int copy_sighand(unsigned long clone_flags, struct task_struct *tsk) | |||
935 | 936 | ||
936 | void __cleanup_sighand(struct sighand_struct *sighand) | 937 | void __cleanup_sighand(struct sighand_struct *sighand) |
937 | { | 938 | { |
938 | if (atomic_dec_and_test(&sighand->count)) | 939 | if (atomic_dec_and_test(&sighand->count)) { |
940 | signalfd_cleanup(sighand); | ||
939 | kmem_cache_free(sighand_cachep, sighand); | 941 | kmem_cache_free(sighand_cachep, sighand); |
942 | } | ||
940 | } | 943 | } |
941 | 944 | ||
942 | 945 | ||