Version:
~ [ 0.6-2.3.46 ] ~
Architecture:
~ [ um ] ~
** Warning: Cannot open xref database.
1 #include "linux/stddef.h"
2 #include "linux/sys.h"
3 #include "linux/sched.h"
4 #include "linux/wait.h"
5 #include "linux/kernel.h"
6 #include "linux/smp_lock.h"
7 #include "asm/signal.h"
8 #include "asm/uaccess.h"
9 #include "user_util.h"
10 #include "kern_util.h"
11 #include "kern.h"
12
13 #define _S(nr) (1<<((nr)-1))
14
15 #define _BLOCKABLE (~(_S(SIGKILL) | _S(SIGSTOP)))
16
17 void deliver_signals(void *t)
18 {
19 struct task_struct *task;
20 unsigned long handler;
21 int i, signal;
22
23 task = t;
24 if(task->thread.npending == 0) return;
25 for(i=task->thread.npending-1;i>=0;i--){
26 signal = task->thread.signals[i].signal;
27 handler = task->thread.signals[i].handler;
28 task->thread.npending--;
29 signal_handler(task, handler, signal);
30 }
31 sigdelsetmask(&task->thread.saved_sigs, ~_BLOCKABLE);
32 spin_lock_irq(&task->sigmask_lock);
33 task->blocked = task->thread.saved_sigs;
34 recalc_sigpending(task);
35 spin_unlock_irq(&task->sigmask_lock);
36 }
37
38 /*
39 * OK, we're invoking a handler
40 */
41 static int handle_signal(struct task_struct *task, unsigned long signr,
42 struct k_sigaction *ka, sigset_t *oldset, int *error)
43 {
44 __sighandler_t handler;
45 sigset_t save;
46 int ret = 0;
47
48 if((error != NULL) && (*error != 0)){
49 switch (*error) {
50 case -ERESTARTNOHAND:
51 *error = -EINTR;
52 break;
53
54 case -ERESTARTSYS:
55 if (!(ka->sa.sa_flags & SA_RESTART)) {
56 *error = -EINTR;
57 break;
58 }
59 /* fallthrough */
60 case -ERESTARTNOINTR:
61 ret = 1;
62 break;
63 }
64 }
65 handler = ka->sa.sa_handler;
66
67 save = *oldset;
68
69 if (ka->sa.sa_flags & SA_ONESHOT)
70 ka->sa.sa_handler = SIG_DFL;
71
72 if (!(ka->sa.sa_flags & SA_NODEFER)) {
73 spin_lock_irq(&task->sigmask_lock);
74 sigorsets(&task->blocked,¤t->blocked,&ka->sa.sa_mask);
75 sigaddset(&task->blocked,signr);
76 recalc_sigpending(task);
77 spin_unlock_irq(&task->sigmask_lock);
78 }
79
80 if(task->thread.npending ==
81 sizeof(task->thread.signals)/sizeof(task->thread.signals[0]))
82 panic("Too many queued signals");
83 task->thread.signals[task->thread.npending].signal = signr;
84 task->thread.signals[task->thread.npending++].handler =
85 (unsigned long) handler;
86 task->thread.saved_sigs = save;
87
88 return(ret);
89 }
90
91 extern int sys_wait4(pid_t pid,unsigned int * stat_addr, int options,
92 struct rusage * ru);
93
94 /*
95 * Note that 'init' is a special process: it doesn't get signals it doesn't
96 * want to handle. Thus you cannot kill init even with a SIGKILL even by
97 * mistake.
98 *
99 * Note that we go through the signals twice: once to check the signals that
100 * the kernel can handle, and then we build all the user-level signal handling
101 * stack-frames in one go after that.
102 */
103 int do_signal(void *t, int *error, int *signalled)
104 {
105 struct task_struct *task;
106 sigset_t *oldset;
107 siginfo_t info;
108 struct k_sigaction *ka;
109 int ret;
110
111 task = t;
112 if(task == NULL) task = current;
113 oldset = &task->blocked;
114
115 if(signalled != NULL) *signalled = 0;
116 for (;;) {
117 unsigned long signr;
118
119 spin_lock_irq(&task->sigmask_lock);
120 signr = dequeue_signal(&task->blocked, &info);
121 spin_unlock_irq(&task->sigmask_lock);
122
123 if (!signr)
124 break;
125
126 if(signalled != NULL) *signalled = 1;
127
128 if ((task->flags & PF_PTRACED) && signr != SIGKILL) {
129 /* Let the debugger run. */
130 task->exit_code = signr;
131 task->state = TASK_STOPPED;
132 notify_parent(task, SIGCHLD);
133 schedule();
134
135 /* We're back. Did the debugger cancel the sig? */
136 if (!(signr = task->exit_code))
137 continue;
138 task->exit_code = 0;
139
140 /* The debugger continued. Ignore SIGSTOP. */
141 if (signr == SIGSTOP)
142 continue;
143
144 /* Update the siginfo structure. Is this good? */
145 if (signr != info.si_signo) {
146 info.si_signo = signr;
147 info.si_errno = 0;
148 info.si_code = SI_USER;
149 info.si_pid = task->p_pptr->pid;
150 info.si_uid = task->p_pptr->uid;
151 }
152
153 /* If the (new) signal is now blocked, requeue it. */
154 if (sigismember(&task->blocked, signr)) {
155 send_sig_info(signr, &info, task);
156 continue;
157 }
158 }
159
160 ka = &task->sig->action[signr-1];
161 if (ka->sa.sa_handler == SIG_IGN) {
162 if (signr != SIGCHLD)
163 continue;
164 /* Check for SIGCHLD: it's special. */
165 while (sys_wait4(-1, NULL, WNOHANG, NULL) > 0)
166 /* nothing */;
167 continue;
168 }
169
170 if (ka->sa.sa_handler == SIG_DFL) {
171 int exit_code = signr;
172
173 /* Init gets no signals it doesn't want. */
174 if (task->pid == 1)
175 continue;
176
177 switch (signr) {
178 case SIGCONT: case SIGCHLD: case SIGWINCH:
179 continue;
180
181 case SIGTSTP: case SIGTTIN: case SIGTTOU:
182 if (is_orphaned_pgrp(task->pgrp))
183 continue;
184 /* FALLTHRU */
185
186 case SIGSTOP:
187 task->state = TASK_STOPPED;
188 task->exit_code = signr;
189 if (!(task->p_pptr->sig->action[SIGCHLD-1].sa.sa_flags & SA_NOCLDSTOP))
190 notify_parent(task, SIGCHLD);
191 schedule();
192 continue;
193
194 case SIGQUIT: case SIGILL: case SIGTRAP:
195 case SIGABRT: case SIGFPE: case SIGSEGV:
196 case SIGBUS: case SIGSYS: case SIGXCPU: case SIGXFSZ:
197 lock_kernel();
198 if (task->binfmt
199 && task->binfmt->core_dump
200 && task->binfmt->core_dump(signr, NULL,
201 NULL))
202 exit_code |= 0x80;
203 unlock_kernel();
204 /* FALLTHRU */
205
206 default:
207 lock_kernel();
208 sigaddset(&task->signal, signr);
209 recalc_sigpending(task);
210 task->flags |= PF_SIGNALED;
211 do_exit(exit_code);
212 /* NOTREACHED */
213 }
214 }
215
216 /* Whee! Actually deliver the signal. */
217 ret = handle_signal(task, signr, ka, oldset, error);
218 if(ret != 0) return(ret);
219 }
220 return(0);
221 }
222
223 int sys_rt_sigsuspend(sigset_t *unewset, size_t sigsetsize)
224 {
225 sigset_t saveset, newset;
226
227 /* XXX: Don't preclude handling different sized sigset_t's. */
228 if (sigsetsize != sizeof(sigset_t))
229 return -EINVAL;
230
231 if (copy_from_user(&newset, unewset, sizeof(newset)))
232 return -EFAULT;
233 sigdelsetmask(&newset, ~_BLOCKABLE);
234
235 spin_lock_irq(¤t->sigmask_lock);
236 saveset = current->blocked;
237 current->blocked = newset;
238 recalc_sigpending(current);
239 spin_unlock_irq(¤t->sigmask_lock);
240 return(0);
241 }
242
This page was automatically generated by the
LXR engine.
Visit the LXR main site for more
information.