1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20: #include <stdio.h>
21: #include <stdlib.h>
22: #include <string.h>
23:
24: #include <cthreads.h>
25: #include <mach.h>
26: #include <mach/thread_switch.h>
27:
28: #include <hurd.h>
29: #include <hurd/id.h>
30: #include <hurd/signal.h>
31:
32: #include "hurdfault.h"
33: #include "hurdmalloc.h"
34: #include "../locale/localeinfo.h"
35:
36: const char *_hurdsig_getenv (const char *);
37:
38: struct mutex _hurd_siglock;
39: int _hurd_stopped;
40:
41:
42: mach_port_t _hurd_msgport;
43:
44:
45: thread_t _hurd_msgport_thread;
46:
47:
48: thread_t _hurd_sigthread;
49:
50:
51: unsigned long int __hurd_sigthread_stack_base;
52: unsigned long int __hurd_sigthread_stack_end;
53: unsigned long int *__hurd_sigthread_variables;
54:
55:
56: struct hurd_sigstate *_hurd_sigstates;
57:
58:
59: mach_msg_timeout_t _hurd_interrupted_rpc_timeout = 3000;
60: ^L
61: static void
62: default_sigaction (struct sigaction actions[NSIG])
63: {
64: int signo;
65:
66: __sigemptyset (&actions[0].sa_mask);
67: actions[0].sa_flags = SA_RESTART;
68: actions[0].sa_handler = SIG_DFL;
69:
70: for (signo = 1; signo < NSIG; ++signo)
71: actions[signo] = actions[0];
72: }
73:
74: struct hurd_sigstate *
75: _hurd_thread_sigstate (thread_t thread)
76: {
77: struct hurd_sigstate *ss;
78: __mutex_lock (&_hurd_siglock);
79: for (ss = _hurd_sigstates; ss != NULL; ss = ss->next)
80: if (ss->thread == thread)
81: break;
82: if (ss == NULL)
83: {
84: ss = malloc (sizeof (*ss));
85: if (ss == NULL)
86: __libc_fatal ("hurd: Can't allocate thread sigstate\n");
87: ss->thread = thread;
88: __spin_lock_init (&ss->lock);
89:
90:
91: __sigemptyset (&ss->blocked);
92: __sigemptyset (&ss->pending);
93: memset (&ss->sigaltstack, 0, sizeof (ss->sigaltstack));
94: ss->preemptors = NULL;
95: ss->suspended = MACH_PORT_NULL;
96: ss->intr_port = MACH_PORT_NULL;
97: ss->context = NULL;
98:
99:
100:
101: if (thread == _hurd_sigthread)
102: default_sigaction (ss->actions);
103: else
104: {
105: struct hurd_sigstate *s;
106: for (s = _hurd_sigstates; s != NULL; s = s->next)
107: if (s->thread == _hurd_sigthread)
108: break;
109: if (s)
110: {
111: __spin_lock (&s->lock);
112: memcpy (ss->actions, s->actions, sizeof (s->actions));
113: __spin_unlock (&s->lock);
114: }
115: else
116: default_sigaction (ss->actions);
117: }
118:
119: ss->next = _hurd_sigstates;
120: _hurd_sigstates = ss;
121: }
122: __mutex_unlock (&_hurd_siglock);
123: return ss;
124: }
125: ^L
126:
127:
128: #include <hurd/fd.h>
129: #include <hurd/crash.h>
130: #include <hurd/resource.h>
131: #include <hurd/paths.h>
132: #include <setjmp.h>
133: #include <fcntl.h>
134: #include <sys/wait.h>
135: #include <thread_state.h>
136: #include <hurd/msg_server.h>
137: #include <hurd/msg_reply.h>
138: #include <hurd/interrupt.h>
139: #include <assert.h>
140: #include <unistd.h>
141:
142:
143:
144:
145: static int
146: write_corefile (int signo, const struct hurd_signal_detail *detail)
147: {
148: error_t err;
149: mach_port_t coreserver;
150: file_t file, coredir;
151: const char *name;
152:
153:
154: rlim_t corelimit = _hurd_rlimits[RLIMIT_CORE].rlim_cur;
155:
156: if (corelimit == 0)
157:
158:
159:
160: return 0;
161:
162:
163:
164:
165:
166:
167:
168: coreserver = MACH_PORT_NULL;
169: name = _hurdsig_getenv ("CRASHSERVER");
170: if (name != NULL)
171: coreserver = __file_name_lookup (name, 0, 0);
172: if (coreserver == MACH_PORT_NULL)
173: coreserver = __file_name_lookup (_SERVERS_CRASH, 0, 0);
174: if (coreserver == MACH_PORT_NULL)
175: return 0;
176:
177:
178: file = MACH_PORT_NULL;
179: name = _hurdsig_getenv ("COREFILE");
180: if (name == NULL)
181: name = "core";
182: coredir = __file_name_split (name, (char **) &name);
183: if (coredir != MACH_PORT_NULL)
184:
185: __dir_mkfile (coredir, O_WRONLY|O_CREAT,
186: 0600 & ~_hurd_umask,
187: &file);
188:
189:
190: err = __crash_dump_task (coreserver,
191: __mach_task_self (),
192: file,
193: signo, detail->code, detail->error,
194: detail->exc, detail->exc_code, detail->exc_subcode,
195: _hurd_ports[INIT_PORT_CTTYID].port,
196: MACH_MSG_TYPE_COPY_SEND);
197: __mach_port_deallocate (__mach_task_self (), coreserver);
198:
199: if (! err && file != MACH_PORT_NULL)
200:
201:
202: err = __dir_link (coredir, file, name, 1);
203: __mach_port_deallocate (__mach_task_self (), file);
204: __mach_port_deallocate (__mach_task_self (), coredir);
205: return !err && file != MACH_PORT_NULL;
206: }
207:
208:
209:
210:
211:
212: #define THREAD_ABORTED 1
213:
214:
215: static void
216: abort_thread (struct hurd_sigstate *ss, struct machine_thread_all_state *state,
217: void (*reply) (void))
218: {
219: if (!(state->set & THREAD_ABORTED))
220: {
221: error_t err = __thread_abort (ss->thread);
222: assert_perror (err);
223:
224:
225: state->set = THREAD_ABORTED;
226: }
227:
228: if (reply)
229: (*reply) ();
230:
231: machine_get_basic_state (ss->thread, state);
232: }
233:
234:
235:
236:
237:
238: static mach_port_t *
239: interrupted_reply_port_location (struct machine_thread_all_state *thread_state,
240: int sigthread)
241: {
242: mach_port_t *portloc = (mach_port_t *) __hurd_threadvar_location_from_sp
243: (_HURD_THREADVAR_MIG_REPLY, (void *) thread_state->basic.SP);
244:
245: if (sigthread && _hurdsig_catch_memory_fault (portloc))
246:
247: return NULL;
248:
249:
250: *(volatile mach_port_t *) portloc = *portloc;
251:
252: if (sigthread)
253: _hurdsig_end_catch_fault ();
254:
255: return portloc;
256: }
257: ^L
258: #include <hurd/sigpreempt.h>
259: #include <intr-msg.h>
260:
261:
262: mach_msg_timeout_t _hurdsig_interrupt_timeout = 1000;
263:
264:
265:
266:
267:
268:
269:
270:
271:
272:
273:
274:
275:
276:
277:
278:
279:
280:
281:
282: mach_port_t
283: _hurdsig_abort_rpcs (struct hurd_sigstate *ss, int signo, int sigthread,
284: struct machine_thread_all_state *state, int *state_change,
285: void (*reply) (void))
286: {
287: extern const void _hurd_intr_rpc_msg_in_trap;
288: mach_port_t rcv_port = MACH_PORT_NULL;
289: mach_port_t intr_port;
290:
291: *state_change = 0;
292:
293: intr_port = ss->intr_port;
294: if (intr_port == MACH_PORT_NULL)
295:
296: return MACH_PORT_NULL;
297:
298:
299:
300: abort_thread (ss, state, reply);
301:
302: if (state->basic.PC < (natural_t) &_hurd_intr_rpc_msg_in_trap)
303: {
304:
305:
306:
307: INTR_MSG_BACK_OUT (&state->basic);
308: MACHINE_THREAD_STATE_SET_PC (&state->basic,
309: &_hurd_intr_rpc_msg_in_trap);
310: state->basic.SYSRETURN = MACH_SEND_INTERRUPTED;
311: *state_change = 1;
312: }
313: else if (state->basic.PC == (natural_t) &_hurd_intr_rpc_msg_in_trap &&
314:
315:
316:
317: state->basic.SYSRETURN == MACH_RCV_INTERRUPTED)
318: {
319:
320:
321:
322:
323:
324:
325:
326:
327:
328: mach_port_t *reply = interrupted_reply_port_location (state,
329: sigthread);
330: error_t err = __interrupt_operation (intr_port, _hurdsig_interrupt_timeout);
331:
332: if (err)
333: {
334: if (reply)
335: {
336:
337:
338: __mach_port_destroy (__mach_task_self (), *reply);
339: *reply = MACH_PORT_NULL;
340: }
341:
342:
343:
344:
345:
346:
347:
348: state->basic.SYSRETURN = EINTR;
349: *state_change = 1;
350: }
351: else if (reply)
352: rcv_port = *reply;
353:
354:
355:
356:
357:
358: if (! signo || !(ss->actions[signo].sa_flags & SA_RESTART))
359: ss->intr_port = MACH_PORT_NULL;
360: }
361:
362: return rcv_port;
363: }
364:
365:
366:
367:
368:
369:
370:
371:
372: static void
373: abort_all_rpcs (int signo, struct machine_thread_all_state *state, int live)
374: {
375:
376:
377:
378:
379: struct hurd_sigstate *ss;
380: size_t nthreads;
381: mach_port_t *reply_ports;
382:
383:
384:
385: nthreads = 0;
386: for (ss = _hurd_sigstates; ss != NULL; ss = ss->next)
387: ++nthreads;
388:
389: reply_ports = alloca (nthreads * sizeof *reply_ports);
390:
391: nthreads = 0;
392: for (ss = _hurd_sigstates; ss != NULL; ss = ss->next, ++nthreads)
393: if (ss->thread == _hurd_msgport_thread)
394: reply_ports[nthreads] = MACH_PORT_NULL;
395: else
396: {
397: int state_changed;
398: state->set = 0;
399:
400:
401:
402:
403: reply_ports[nthreads] = _hurdsig_abort_rpcs (ss, signo, 1,
404: state, &state_changed,
405: NULL);
406: if (live)
407: {
408: if (reply_ports[nthreads] != MACH_PORT_NULL)
409: {
410:
411:
412:
413: state->basic.SYSRETURN = EINTR;
414: state_changed = 1;
415: }
416: if (state_changed)
417:
418:
419: __thread_set_state (ss->thread, MACHINE_THREAD_STATE_FLAVOR,
420: (natural_t *) &state->basic,
421: MACHINE_THREAD_STATE_COUNT);
422: }
423: }
424:
425:
426: while (nthreads-- > 0)
427: if (reply_ports[nthreads] != MACH_PORT_NULL)
428: {
429: error_t err;
430: mach_msg_header_t head;
431: err = __mach_msg (&head, MACH_RCV_MSG|MACH_RCV_TIMEOUT, 0, sizeof head,
432: reply_ports[nthreads],
433: _hurd_interrupted_rpc_timeout, MACH_PORT_NULL);
434: switch (err)
435: {
436: case MACH_RCV_TIMED_OUT:
437: case MACH_RCV_TOO_LARGE:
438: break;
439:
440: default:
441: assert_perror (err);
442: }
443: }
444: }
445:
446: struct hurd_signal_preemptor *_hurdsig_preemptors = 0;
447: sigset_t _hurdsig_preempted_set;
448:
449:
450: weak_alias (_hurdsig_preemptors, _hurdsig_preempters)
451:
452:
453: #define STOPSIGS (sigmask (SIGTTIN) | sigmask (SIGTTOU) | \
454: sigmask (SIGSTOP) | sigmask (SIGTSTP))
455:
456:
457: void
458: _hurd_internal_post_signal (struct hurd_sigstate *ss,
459: int signo, struct hurd_signal_detail *detail,
460: mach_port_t reply_port,
461: mach_msg_type_name_t reply_port_type,
462: int untraced)
463: {
464: error_t err;
465: struct machine_thread_all_state thread_state;
466: enum { stop, ignore, core, term, handle } act;
467: sighandler_t handler;
468: sigset_t pending;
469: int ss_suspended;
470:
471:
472: __typeof (__msg_sig_post_reply) *reply_rpc
473: = (untraced ? __msg_sig_post_untraced_reply : __msg_sig_post_reply);
474: void reply (void)
475: {
476: error_t err;
477: if (reply_port == MACH_PORT_NULL)
478: return;
479: err = (*reply_rpc) (reply_port, reply_port_type, 0);
480: reply_port = MACH_PORT_NULL;
481: if (err != MACH_SEND_INVALID_DEST)
482: assert_perror (err);
483: }
484:
485:
486: void mark_pending (void)
487: {
488: __sigaddset (&ss->pending, signo);
489:
490:
491: ss->pending_data[signo] = *detail;
492: }
493:
494:
495: void suspend (void)
496: {
497:
498: __USEPORT (PROC,
499: ({
500:
501:
502: __mutex_lock (&_hurd_siglock);
503: __proc_dostop (port, _hurd_msgport_thread);
504: __mutex_unlock (&_hurd_siglock);
505: abort_all_rpcs (signo, &thread_state, 1);
506: reply ();
507: __proc_mark_stop (port, signo, detail->code);
508: }));
509: _hurd_stopped = 1;
510: }
511:
512: void resume (void)
513: {
514:
515: thread_t *threads;
516: mach_msg_type_number_t nthreads, i;
517: error_t err;
518:
519: if (! _hurd_stopped)
520: return;
521:
522:
523: __USEPORT (PROC, __proc_mark_cont (port));
524:
525: err = __task_threads (__mach_task_self (), &threads, &nthreads);
526: assert_perror (err);
527: for (i = 0; i < nthreads; ++i)
528: {
529: if (threads[i] != _hurd_msgport_thread &&
530: (act != handle || threads[i] != ss->thread))
531: {
532: err = __thread_resume (threads[i]);
533: assert_perror (err);
534: }
535: err = __mach_port_deallocate (__mach_task_self (),
536: threads[i]);
537: assert_perror (err);
538: }
539: __vm_deallocate (__mach_task_self (),
540: (vm_address_t) threads,
541: nthreads * sizeof *threads);
542: _hurd_stopped = 0;
543: if (act == handle)
544:
545: ss_suspended = 1;
546: }
547:
548: if (signo == 0)
549: {
550: if (untraced)
551:
552: resume ();
553:
554:
555: __spin_lock (&ss->lock);
556: goto check_pending_signals;
557: }
558:
559: post_signal:
560:
561: thread_state.set = 0;
562:
563: __spin_lock (&ss->lock);
564:
565:
566:
567: {
568: inline sighandler_t try_preemptor (struct hurd_signal_preemptor *pe)
569: {
570: do
571: {
572: if (HURD_PREEMPT_SIGNAL_P (pe, signo, detail->code))
573: {
574: if (pe->preemptor)
575: {
576: sighandler_t handler = (*pe->preemptor) (pe, ss,
577: &signo, detail);
578: if (handler != SIG_ERR)
579: return handler;
580: }
581: else
582: return pe->handler;
583: }
584: pe = pe->next;
585: } while (pe != 0);
586: return SIG_ERR;
587: }
588:
589: handler = ss->preemptors ? try_preemptor (<