aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/eventpoll.c4
-rw-r--r--fs/signalfd.c11
-rw-r--r--include/asm-generic/poll.h2
-rw-r--r--include/linux/signalfd.h5
-rw-r--r--kernel/fork.c5
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
33void 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
33struct signalfd_ctx { 44struct 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
31struct pollfd { 33struct 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
64extern void signalfd_cleanup(struct sighand_struct *sighand);
65
64#else /* CONFIG_SIGNALFD */ 66#else /* CONFIG_SIGNALFD */
65 67
66static inline void signalfd_notify(struct task_struct *tsk, int sig) { } 68static inline void signalfd_notify(struct task_struct *tsk, int sig) { }
67 69
70static 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
936void __cleanup_sighand(struct sighand_struct *sighand) 937void __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