| @@ -11,8 +11,10 @@ · 10 unmodified lines |
| 11 | * Now using anonymous inode source. | 11 | * Now using anonymous inode source. |
| 12 | * Thanks to Oleg Nesterov for useful code review and suggestions. | 12 | * Thanks to Oleg Nesterov for useful code review and suggestions. |
| 13 | * More comments and suggestions from Arnd Bergmann. | 13 | * More comments and suggestions from Arnd Bergmann. |
| 14 | * Sat May 19, 2007: Davi E. M. Arnaut <davi@haxent.com.br> | 14 | * Sat May 19, 2007: Davi E. M. Arnaut <davi@haxent.com.br> |
| 15 | * Retrieve multiple signals with one read() call | 15 | * Retrieve multiple signals with one read() call |
| | 16 | * Sun Jul 15, 2007: Davide Libenzi <davidel@xmailserver.org> |
| | 17 | * Attach to the sighand only during read() and poll(). |
| 16 | */ | 18 | */ |
| 17 | | 19 | |
| 18 | #include <linux/file.h> | 20 | #include <linux/file.h> |
| @@ -27,102 +29,12 @@ · 8 unmodified lines |
| 27 | #include <linux/signalfd.h> | 29 | #include <linux/signalfd.h> |
| 28 | | 30 | |
| 29 | struct signalfd_ctx { | 31 | struct signalfd_ctx { |
| 30 | struct list_head lnk; | | |
| 31 | wait_queue_head_t wqh; | | |
| 32 | sigset_t sigmask; | 32 | sigset_t sigmask; |
| 33 | struct task_struct *tsk; | | |
| 34 | }; | 33 | }; |
| 35 | | 34 | |
| 36 | struct signalfd_lockctx { | | |
| 37 | struct task_struct *tsk; | | |
| 38 | unsigned long flags; | | |
| 39 | }; | | |
| 40 | | | |
| 41 | /* | | |
| 42 | * Tries to acquire the sighand lock. We do not increment the sighand | | |
| 43 | * use count, and we do not even pin the task struct, so we need to | | |
| 44 | * do it inside an RCU read lock, and we must be prepared for the | | |
| 45 | * ctx->tsk going to NULL (in signalfd_deliver()), and for the sighand | | |
| 46 | * being detached. We return 0 if the sighand has been detached, or | | |
| 47 | * 1 if we were able to pin the sighand lock. | | |
| 48 | */ | | |
| 49 | static int signalfd_lock(struct signalfd_ctx *ctx, struct signalfd_lockctx *lk) | | |
| 50 | { | | |
| 51 | struct sighand_struct *sighand = NULL; | | |
| 52 | | | |
| 53 | rcu_read_lock(); | | |
| 54 | lk->tsk = rcu_dereference(ctx->tsk); | | |
| 55 | if (likely(lk->tsk != NULL)) | | |
| 56 | sighand = lock_task_sighand(lk->tsk, &lk->flags); | | |
| 57 | rcu_read_unlock(); | | |
| 58 | | | |
| 59 | if (!sighand) | | |
| 60 | return 0; | | |
| 61 | | | |
| 62 | if (!ctx->tsk) { | | |
| 63 | unlock_task_sighand(lk->tsk, &lk->flags); | | |
| 64 | return 0; | | |
| 65 | } | | |
| 66 | | | |
| 67 | if (lk->tsk->tgid == current->tgid) | | |
| 68 | lk->tsk = current; | | |
| 69 | | | |
| 70 | return 1; | | |
| 71 | } | | |
| 72 | | | |
| 73 | static void signalfd_unlock(struct signalfd_lockctx *lk) | | |
| 74 | { | | |
| 75 | unlock_task_sighand(lk->tsk, &lk->flags); | | |
| 76 | } | | |
| 77 | | | |
| 78 | /* | | |
| 79 | * This must be called with the sighand lock held. | | |
| 80 | */ | | |
| 81 | void signalfd_deliver(struct task_struct *tsk, int sig) | | |
| 82 | { | | |
| 83 | struct sighand_struct *sighand = tsk->sighand; | | |
| 84 | struct signalfd_ctx *ctx, *tmp; | | |
| 85 | | | |
| 86 | BUG_ON(!sig); | | |
| 87 | list_for_each_entry_safe(ctx, tmp, &sighand->signalfd_list, lnk) { | | |
| 88 | /* | | |
| 89 | * We use a negative signal value as a way to broadcast that the | | |
| 90 | * sighand has been orphaned, so that we can notify all the | | |
| 91 | * listeners about this. Remember the ctx->sigmask is inverted, | | |
| 92 | * so if the user is interested in a signal, that corresponding | | |
| 93 | * bit will be zero. | | |
| 94 | */ | | |
| 95 | if (sig < 0) { | | |
| 96 | if (ctx->tsk == tsk) { | | |
| 97 | ctx->tsk = NULL; | | |
| 98 | list_del_init(&ctx->lnk); | | |
| 99 | wake_up(&ctx->wqh); | | |
| 100 | } | | |
| 101 | } else { | | |
| 102 | if (!sigismember(&ctx->sigmask, sig)) | | |
| 103 | wake_up(&ctx->wqh); | | |
| 104 | } | | |
| 105 | } | | |
| 106 | } | | |
| 107 | | | |
| 108 | static void signalfd_cleanup(struct signalfd_ctx *ctx) | | |
| 109 | { | | |
| 110 | struct signalfd_lockctx lk; | | |
| 111 | | | |
| 112 | /* | | |
| 113 | * This is tricky. If the sighand is gone, we do not need to remove | | |
| 114 | * context from the list, the list itself won't be there anymore. | | |
| 115 | */ | | |
| 116 | if (signalfd_lock(ctx, &lk)) { | | |
| 117 | list_del(&ctx->lnk); | | |
| 118 | signalfd_unlock(&lk); | | |
| 119 | } | | |
| 120 | kfree(ctx); | | |
| 121 | } | | |
| 122 | | | |
| 123 | static int signalfd_release(struct inode *inode, struct file *file) | 35 | static int signalfd_release(struct inode *inode, struct file *file) |
| 124 | { | 36 | { |
| 125 | signalfd_cleanup(file->private_data); | 37 | kfree(file->private_data); |
| 126 | return 0; | 38 | return 0; |
| 127 | } | 39 | } |
| 128 | | 40 | |
| @@ -130,23 +42,15 @@ static unsigned int signalfd_poll(struct file *file, poll_table *wait) · 1 unmodified line |
| 130 | { | 42 | { |
| 131 | struct signalfd_ctx *ctx = file->private_data; | 43 | struct signalfd_ctx *ctx = file->private_data; |
| 132 | unsigned int events = 0; | 44 | unsigned int events = 0; |
| 133 | struct signalfd_lockctx lk; | | |
| 134 | | 45 | |
| 135 | poll_wait(file, &ctx->wqh, wait); | 46 | poll_wait(file, ¤t->sighand->signalfd_wqh, wait); |
| 136 | | 47 | |
| 137 | /* | 48 | spin_lock_irq(¤t->sighand->siglock); |
| 138 | * Let the caller get a POLLIN in this case, ala socket recv() when | 49 | if (next_signal(¤t->pending, &ctx->sigmask) || |
| 139 | * the peer disconnects. | 50 | next_signal(¤t->signal->shared_pending, |
| 140 | */ | 51 | &ctx->sigmask)) |
| 141 | if (signalfd_lock(ctx, &lk)) { | | |
| 142 | if ((lk.tsk == current && | | |
| 143 | next_signal(&lk.tsk->pending, &ctx->sigmask) > 0) || | | |
| 144 | next_signal(&lk.tsk->signal->shared_pending, | | |
| 145 | &ctx->sigmask) > 0) | | |
| 146 | events |= POLLIN; | | |
| 147 | signalfd_unlock(&lk); | | |
| 148 | } else | | |
| 149 | events |= POLLIN; | 52 | events |= POLLIN; |
| | 53 | spin_unlock_irq(¤t->sighand->siglock); |
| 150 | | 54 | |
| 151 | return events; | 55 | return events; |
| 152 | } | 56 | } |
| @@ -219,59 +123,46 @@ static ssize_t signalfd_dequeue(struct signalfd_ctx *ctx, siginfo_t *info, · 66 unmodified lines |
| 219 | int nonblock) | 123 | int nonblock) |
| 220 | { | 124 | { |
| 221 | ssize_t ret; | 125 | ssize_t ret; |
| 222 | struct signalfd_lockctx lk; | | |
| 223 | DECLARE_WAITQUEUE(wait, current); | 126 | DECLARE_WAITQUEUE(wait, current); |
| 224 | | 127 | |
| 225 | if (!signalfd_lock(ctx, &lk)) | 128 | spin_lock_irq(¤t->sighand->siglock); |
| 226 | return 0; | 129 | ret = dequeue_signal(current, &ctx->sigmask, info); |
| 227 | | | |
| 228 | ret = dequeue_signal(lk.tsk, &ctx->sigmask, info); | | |
| 229 | switch (ret) { | 130 | switch (ret) { |
| 230 | case 0: | 131 | case 0: |
| 231 | if (!nonblock) | 132 | if (!nonblock) |
| 232 | break; | 133 | break; |
| 233 | ret = -EAGAIN; | 134 | ret = -EAGAIN; |
| 234 | default: | 135 | default: |
| 235 | signalfd_unlock(&lk); | 136 | spin_unlock_irq(¤t->sighand->siglock); |
| 236 | return ret; | 137 | return ret; |
| 237 | } | 138 | } |
| 238 | | 139 | |
| 239 | add_wait_queue(&ctx->wqh, &wait); | 140 | add_wait_queue(¤t->sighand->signalfd_wqh, &wait); |
| 240 | for (;;) { | 141 | for (;;) { |
| 241 | set_current_state(TASK_INTERRUPTIBLE); | 142 | set_current_state(TASK_INTERRUPTIBLE); |
| 242 | ret = dequeue_signal(lk.tsk, &ctx->sigmask, info); | 143 | ret = dequeue_signal(current, &ctx->sigmask, info); |
| 243 | signalfd_unlock(&lk); | | |
| 244 | if (ret != 0) | 144 | if (ret != 0) |
| 245 | break; | 145 | break; |
| 246 | if (signal_pending(current)) { | 146 | if (signal_pending(current)) { |
| 247 | ret = -ERESTARTSYS; | 147 | ret = -ERESTARTSYS; |
| 248 | break; | 148 | break; |
| 249 | } | 149 | } |
| | 150 | spin_unlock_irq(¤t->sighand->siglock); |
| 250 | schedule(); | 151 | schedule(); |
| 251 | ret = signalfd_lock(ctx, &lk); | 152 | spin_lock_irq(¤t->sighand->siglock); |
| 252 | if (unlikely(!ret)) { | | |
| 253 | /* | | |
| 254 | * Let the caller read zero byte, ala socket | | |
| 255 | * recv() when the peer disconnect. This test | | |
| 256 | * must be done before doing a dequeue_signal(), | | |
| 257 | * because if the sighand has been orphaned, | | |
| 258 | * the dequeue_signal() call is going to crash | | |
| 259 | * because ->sighand will be long gone. | | |
| 260 | */ | | |
| 261 | break; | | |
| 262 | } | | |
| 263 | } | 153 | } |
| | 154 | spin_unlock_irq(¤t->sighand->siglock); |
| 264 | | 155 | |
| 265 | remove_wait_queue(&ctx->wqh, &wait); | 156 | remove_wait_queue(¤t->sighand->signalfd_wqh, &wait); |
| 266 | __set_current_state(TASK_RUNNING); | 157 | __set_current_state(TASK_RUNNING); |
| 267 | | 158 | |
| 268 | return ret; | 159 | return ret; |
| 269 | } | 160 | } |
| 270 | | 161 | |
| 271 | /* | 162 | /* |
| 272 | * Returns either the size of a "struct signalfd_siginfo", or zero if the | 163 | * Returns a multiple of the size of a "struct signalfd_siginfo", or a negative |
| 273 | * sighand we are attached to, has been orphaned. The "count" parameter | 164 | * error code. The "count" parameter must be at least the size of a |
| 274 | * must be at least the size of a "struct signalfd_siginfo". | 165 | * "struct signalfd_siginfo". |
| 275 | */ | 166 | */ |
| 276 | static ssize_t signalfd_read(struct file *file, char __user *buf, size_t count, | 167 | static ssize_t signalfd_read(struct file *file, char __user *buf, size_t count, |
| 277 | loff_t *ppos) | 168 | loff_t *ppos) |
| @@ -287,7 +178,6 @@ static ssize_t signalfd_read(struct file *file, char __user *buf, size_t count, · 9 unmodified lines |
| 287 | return -EINVAL; | 178 | return -EINVAL; |
| 288 | | 179 | |
| 289 | siginfo = (struct signalfd_siginfo __user *) buf; | 180 | siginfo = (struct signalfd_siginfo __user *) buf; |
| 290 | | | |
| 291 | do { | 181 | do { |
| 292 | ret = signalfd_dequeue(ctx, &info, nonblock); | 182 | ret = signalfd_dequeue(ctx, &info, nonblock); |
| 293 | if (unlikely(ret <= 0)) | 183 | if (unlikely(ret <= 0)) |
| @@ -300,7 +190,7 @@ static ssize_t signalfd_read(struct file *file, char __user *buf, size_t count, · 6 unmodified lines |
| 300 | nonblock = 1; | 190 | nonblock = 1; |
| 301 | } while (--count); | 191 | } while (--count); |
| 302 | | 192 | |
| 303 | return total ? total : ret; | 193 | return total ? total: ret; |
| 304 | } | 194 | } |
| 305 | | 195 | |
| 306 | static const struct file_operations signalfd_fops = { | 196 | static const struct file_operations signalfd_fops = { |
| @@ -309,20 +199,13 @@ static const struct file_operations signalfd_fops = { · 2 unmodified lines |
| 309 | .read = signalfd_read, | 199 | .read = signalfd_read, |
| 310 | }; | 200 | }; |
| 311 | | 201 | |
| 312 | /* | | |
| 313 | * Create a file descriptor that is associated with our signal | | |
| 314 | * state. We can pass it around to others if we want to, but | | |
| 315 | * it will always be _our_ signal state. | | |
| 316 | */ | | |
| 317 | asmlinkage long sys_signalfd(int ufd, sigset_t __user *user_mask, size_t sizemask) | 202 | asmlinkage long sys_signalfd(int ufd, sigset_t __user *user_mask, size_t sizemask) |
| 318 | { | 203 | { |
| 319 | int error; | 204 | int error; |
| 320 | sigset_t sigmask; | 205 | sigset_t sigmask; |
| 321 | struct signalfd_ctx *ctx; | 206 | struct signalfd_ctx *ctx; |
| 322 | struct sighand_struct *sighand; | | |
| 323 | struct file *file; | 207 | struct file *file; |
| 324 | struct inode *inode; | 208 | struct inode *inode; |
| 325 | struct signalfd_lockctx lk; | | |
| 326 | | 209 | |
| 327 | if (sizemask != sizeof(sigset_t) || | 210 | if (sizemask != sizeof(sigset_t) || |
| 328 | copy_from_user(&sigmask, user_mask, sizeof(sigmask))) | 211 | copy_from_user(&sigmask, user_mask, sizeof(sigmask))) |
| @@ -335,17 +218,7 @@ asmlinkage long sys_signalfd(int ufd, sigset_t __user *user_mask, size_t sizemas · 6 unmodified lines |
| 335 | if (!ctx) | 218 | if (!ctx) |
| 336 | return -ENOMEM; | 219 | return -ENOMEM; |
| 337 | | 220 | |
| 338 | init_waitqueue_head(&ctx->wqh); | | |
| 339 | ctx->sigmask = sigmask; | 221 | ctx->sigmask = sigmask; |
| 340 | ctx->tsk = current->group_leader; | | |
| 341 | | | |
| 342 | sighand = current->sighand; | | |
| 343 | /* | | |
| 344 | * Add this fd to the list of signal listeners. | | |
| 345 | */ | | |
| 346 | spin_lock_irq(&sighand->siglock); | | |
| 347 | list_add_tail(&ctx->lnk, &sighand->signalfd_list); | | |
| 348 | spin_unlock_irq(&sighand->siglock); | | |
| 349 | | 222 | |
| 350 | /* | 223 | /* |
| 351 | * When we call this, the initialization must be complete, since | 224 | * When we call this, the initialization must be complete, since |
| @@ -364,23 +237,18 @@ asmlinkage long sys_signalfd(int ufd, sigset_t __user *user_mask, size_t sizemas · 12 unmodified lines |
| 364 | fput(file); | 237 | fput(file); |
| 365 | return -EINVAL; | 238 | return -EINVAL; |
| 366 | } | 239 | } |
| 367 | /* | 240 | spin_lock_irq(¤t->sighand->siglock); |
| 368 | * We need to be prepared of the fact that the sighand this fd | 241 | ctx->sigmask = sigmask; |
| 369 | * is attached to, has been detched. In that case signalfd_lock() | 242 | spin_unlock_irq(¤t->sighand->siglock); |
| 370 | * will return 0, and we'll just skip setting the new mask. | 243 | |
| 371 | */ | 244 | wake_up(¤t->sighand->signalfd_wqh); |
| 372 | if (signalfd_lock(ctx, &lk)) { | | |
| 373 | ctx->sigmask = sigmask; | | |
| 374 | signalfd_unlock(&lk); | | |
| 375 | } | | |
| 376 | wake_up(&ctx->wqh); | | |
| 377 | fput(file); | 245 | fput(file); |
| 378 | } | 246 | } |
| 379 | | 247 | |
| 380 | return ufd; | 248 | return ufd; |
| 381 | | 249 | |
| 382 | err_fdalloc: | 250 | err_fdalloc: |
| 383 | signalfd_cleanup(ctx); | 251 | kfree(ctx); |
| 384 | return error; | 252 | return error; |
| 385 | } | 253 | } |
| 386 | | 254 | |