|
|
1.1 root 1: /* $Header: /kernel/kersrc/coh.386/RCS/sig.c,v 1.2 92/08/04 12:34:36 bin Exp Locker: bin $ */
2: /* (lgl-
3: * The information contained herein is a trade secret of Mark Williams
4: * Company, and is confidential information. It is provided under a
5: * license agreement, and may be copied or disclosed only under the
6: * terms of that agreement. Any reproduction or disclosure of this
7: * material without the express written authorization of Mark Williams
8: * Company or persuant to the license agreement is unlawful.
9: *
10: * COHERENT Version 2.3.37
11: * Copyright (c) 1982, 1983, 1984.
12: * An unpublished work by Mark Williams Company, Chicago.
13: * All rights reserved.
14: -lgl) */
15: /*
16: * Coherent.
17: * Signal handling.
18: *
19: * $Log: sig.c,v $
20: * Revision 1.2 92/08/04 12:34:36 bin
21: * changed for ker 59
22: *
23: * Revision 1.2 92/01/06 12:00:24 hal
24: * Compile with cc.mwc.
25: *
26: * Revision 1.1 88/03/24 16:14:24 src
27: * Initial revision
28: *
29: * 87/11/05 Allan Cornish /usr/src/sys/coh/sig.c
30: * New seg struct now used to allow extended addressing.
31: *
32: * 86/11/19 Allan Cornish /usr/src/sys/coh/sig.c
33: * sigdump() initializes the (new) (IO).io_flag field to 0.
34: */
35: #include <sys/coherent.h>
36: #include <errno.h>
37: #include <sys/ino.h>
38: #include <sys/inode.h>
39: #include <sys/io.h>
40: #include <sys/proc.h>
41: #include <sys/ptrace.h>
42: #include <sys/sched.h>
43: #include <sys/seg.h>
44: #include <signal.h>
45:
46: /*
47: * Set up the action to be taken on a signal.
48: */
49: usigsys(signal, func)
50: int signal;
51: register void (*func)();
52: {
53: register PROC *pp;
54: register sig_t s;
55: register int (*old_sig)();
56: int sigtype;
57:
58: sigtype = signal & ~0xFF;
59: signal ^= sigtype;
60:
61: pp = SELF;
62: if (signal<=0 || signal>NSIG || signal==SIGKILL) {
63: u.u_error = EINVAL;
64: return;
65: }
66:
67: /*
68: * In order to avoid runaway, don't allow user to set
69: * handler for SIGSEGV to anything but SIG_DFL.
70: *
71: * We should do something more sophisticated, like detecting
72: * two SEGV's in a row and then killing the process.
73: */
74: if (signal == SIGSEGV && func != SIG_DFL) {
75: u.u_error = EINVAL;
76: return;
77: }
78:
79: if (sigtype==SIGDEFER || sigtype==0) {
80: if (func==SIG_IGN)
81: sigtype = SIGIGNORE;
82: if (func==SIG_HOLD)
83: sigtype = SIGHOLD;
84: }
85:
86: s = (sig_t)1 << --signal;
87: if (pp->p_isig&s)
88: old_sig = SIG_IGN;
89: else if (pp->p_hsig&s)
90: old_sig = SIG_HOLD;
91: else
92: old_sig = u.u_sfunc[signal];
93:
94: switch (sigtype) {
95: case SIGHOLD:
96: pp->p_hsig |= s;
97: break;
98: case SIGRELSE:
99: pp->p_hsig &= ~s;
100: if (nondsig()) {
101: T_PIGGY( 0x100, printf("a(s)"); );
102: actvsig();
103: }
104: case SIGIGNORE:
105: pp->p_dfsig &= ~s; /* No longer defaulted. */
106: pp->p_isig |= s; /* Mark signal as ignored. */
107: pp->p_ssig &= ~s; /* Turn off any pending signal. */
108: break;
109: case 0: /* old system entry */
110: case SIGDEFER: /* new system entry */
111: u.u_sigreturn = (void (*)())u.u_regl[EDX];
112: u.u_sfunc[signal] = func;
113: /*
114: * Be sure to mark the signal as defaulted or not.
115: */
116: if (SIG_DFL == func) {
117: pp->p_dfsig |= s;
118: } else {
119: pp->p_dfsig &= ~s;
120: }
121: /*
122: * The signal is no longer ignored or held, and
123: * any pending signal is lost.
124: */
125: pp->p_isig &= ~s;
126: pp->p_hsig &= ~s;
127: pp->p_ssig &= ~s;
128: if (sigtype==SIGDEFER)
129: pp->p_dsig |= s;
130: else
131: pp->p_dsig &= ~s;
132: break;
133: /* SIGPAUSE not done yet */
134: default:
135: u.u_error = SIGSYS;
136: break;
137: }
138: return old_sig;
139: }
140:
141:
142: /*
143: * Send a signal to the process `pp'.
144: */
145: sendsig(sig, pp)
146: register unsigned sig;
147: register PROC *pp;
148: {
149: register sig_t f;
150: register int s;
151:
152:
153: T_PIGGY( 0x40000000,
154: printf("<send sig: %d, id: %d, state: %x, flags: %x, event: %x>",
155: sig, pp->p_pid, pp->p_state, pp->p_flags, pp->p_event);
156: ); /* T_PIGGY() */
157:
158: /*
159: * Convert the signal to a bit position.
160: */
161: f = ((sig_t)1) << (sig-1);
162:
163: /*
164: * If the signal is ignored, do nothing.
165: */
166: if (pp->p_isig&f) {
167: return;
168: }
169:
170: /*
171: * This bit causes SIGCHLD to be ignored here in sendsig().
172: */
173: T_PIGGY( 0x10000000, {
174: if (SIGCHLD == sig) {
175: printf("SIGCHLD ignored, ");
176: return;
177: }
178: }
179: );
180:
181: /*
182: * I do not understand delayed or held signals.
183: */
184: if ((pp->p_ssig & f) && (pp->p_hsig|pp->p_dsig) & f)
185: return;
186:
187: /*
188: * Acutally send the signal by flagging the needed bit.
189: */
190: pp->p_ssig |= f;
191:
192: /*
193: * If the process is sleeping, wake it up so that
194: * it can process this signal.
195: */
196: if (pp->p_state == PSSLEEP) {
197: s = sphi();
198: pp->p_lback->p_lforw = pp->p_lforw;
199: pp->p_lforw->p_lback = pp->p_lback;
200: addu(pp->p_cval, (utimer-pp->p_lctim)*CVCLOCK);
201: setrun(pp);
202: spl(s);
203: }
204: }
205:
206: /*
207: * Return signal number if we have a non ignored or delayed signal, else zero.
208: */
209: nondsig()
210: {
211: register PROC *pp;
212: register sig_t mask;
213: register int signo;
214:
215: pp = SELF;
216: signo = 0;
217: /*
218: * Turn off all ignored signals.
219: */
220: pp->p_ssig &= ~pp->p_isig;
221: /*
222: * If any signals have arrived, but which are not held,
223: * figure out what they are.
224: */
225: if (pp->p_ssig&~pp->p_hsig) {
226: /*
227: * There is at least one signal. Extract its number
228: * from the signal bits.
229: */
230: mask = (sig_t) 1;
231: signo += 1;
232: while (((pp->p_ssig&~pp->p_hsig) & mask) == 0) {
233: mask <<= 1;
234: signo += 1;
235: }
236: }
237: return (signo);
238: }
239:
240: /*
241: * If we have a signal that isn't ignored, activate it.
242: */
243: actvsig()
244: {
245: register int n;
246: register PROC *pp;
247: register int (*func)();
248: sig_t s;
249:
250:
251: /*
252: * Fetch an unprocessed signal.
253: * Return if there are none.
254: */
255: if ((n = nondsig()) == 0)
256: return;
257:
258: T_PIGGY( 0x40000, {
259: if (SIGCHLD == n) {
260: printf("-");
261: return;
262: }
263: } );
264:
265: pp = SELF;
266:
267: /*
268: * Reset the signal to indicate that it has been processed.
269: */
270: --n;
271: pp->p_ssig &= ~((sig_t)1<<n);
272:
273: /*
274: * Fetch the user function that goes with this signal.
275: */
276: func = u.u_sfunc[n];
277:
278: /*
279: * Store the signal number in the u area. This is how
280: * a core dump records the death signal.
281: */
282: u.u_signo = ++n;
283:
284: /*
285: * If the signal is not defaulted, go run the requested
286: * function.
287: */
288: if (func != SIG_DFL) {
289: if (XMODE_286)
290: oldsigstart(n, func);
291: else
292: msigstart(n, func);
293: return;
294: }
295:
296: /*
297: * ASSERTION: the signal being processed is SIG_DFL'd.
298: */
299:
300: /*
301: * msysgen() is a nop for COHERENT 4.0. The comment in the
302: * assembly code is "Nothing useful to save".
303: */
304: msysgen(u.u_sysgen);
305:
306: /*
307: * Do something special for traced processes. (?)
308: */
309: if (pp->p_flags&PFTRAC) {
310: pp->p_flags |= PFWAIT;
311: n = ptret();
312: pp->p_flags &= ~(PFWAIT|PFSTOP);
313: if (n == 0)
314: return;
315: }
316:
317: /*
318: * Some signals cause a core file to be written.
319: */
320: switch(n) {
321: case SIGQUIT:
322: case SIGILL:
323: case SIGTRAP:
324: case SIGABRT:
325: case SIGFPE:
326: case SIGSEGV:
327: case SIGSYS:
328: if (sigdump())
329: n |= 0200;
330: break;
331: }
332: pexit(n);
333: }
334:
335: /*
336: * Create a dump of ourselves onto the file `core'.
337: */
338: sigdump()
339: {
340: register INODE *ip;
341: register SR *srp;
342: register SEG * sp;
343: register int n;
344: register paddr_t ssize;
345: extern int DUMP_LIM;
346:
347: if (SELF->p_flags&PFNDMP)
348: return (0);
349: u.u_io.io_seg = IOSYS;
350: u.u_io.io_flag = 0;
351: /* Make the core with the real owners */
352: schizo();
353: if (ftoi("core", 'c')) {
354: schizo();
355: return (0);
356: }
357: if ((ip=u.u_cdiri) == NULL) {
358: if ((ip=imake(IFREG|0644, 0)) == NULL) {
359: schizo();
360: return (0);
361: }
362: } else {
363: if ((ip->i_mode&IFMT)!=IFREG
364: || iaccess(ip, IPW)==0
365: || getment(ip->i_dev, 1)==NULL) {
366: idetach(ip);
367: schizo();
368: return (0);
369: }
370: iclear(ip);
371: }
372: schizo();
373: u.u_error = 0;
374: u.u_io.io_seek = 0;
375: for (srp=u.u_segl; u.u_error==0 && srp<&u.u_segl[NUSEG]; srp++) {
376: if ((sp = srp->sr_segp)==NULL || (srp->sr_flag&SRFDUMP)==0)
377: continue;
378: u.u_io.io_seg = IOPHY;
379: u.u_io.io.pbase = MAPIO(sp->s_vmem, 0);
380: u.u_io.io_flag = 0;
381: ssize = sp->s_size;
382: if (ssize > DUMP_LIM) {
383: printf("seg %d truncated from %d to %d bytes\n",
384: srp-u.u_segl, ssize, DUMP_LIM);
385: ssize = DUMP_LIM;
386: }
387: sp->s_lrefc++;
388: while (u.u_error == 0 && ssize != 0) {
389: n = ssize > SCHUNK ? SCHUNK : ssize;
390: u.u_io.io_ioc = n;
391: iwrite(ip, &u.u_io);
392: u.u_io.io.pbase += n;
393: ssize -= (paddr_t)n;
394: }
395: sp->s_lrefc--;
396: }
397: idetach(ip);
398: return (u.u_error==0);
399: }
400:
401: /*
402: * Send a ptrace command to the child.
403: */
404: ptset(req, pid, addr, data)
405: unsigned req;
406: int *addr;
407: {
408:
409: register PROC *pp;
410:
411: lock(pnxgate);
412: for (pp=procq.p_nforw; pp!=&procq; pp=pp->p_nforw)
413: if (pp->p_pid == pid)
414: break;
415: unlock(pnxgate);
416: if (pp==&procq || (pp->p_flags&PFSTOP)==0 || pp->p_ppid!=SELF->p_pid){
417: u.u_error = ESRCH;
418: return;
419: }
420: lock(pts.pt_gate);
421: pts.pt_req = req;
422: pts.pt_pid = pid;
423: pts.pt_addr = addr;
424: pts.pt_data = data;
425: pts.pt_errs = 0;
426: pts.pt_rval = 0;
427: pts.pt_busy = 1;
428: wakeup((char *)&pts.pt_req);
429: while (pts.pt_busy) {
430: v_sleep((char *)&pts.pt_busy, CVPTSET, IVPTSET, SVPTSET, "ptrace");
431: /* Send a ptrace command to the child. */
432: }
433: u.u_error = pts.pt_errs;
434: unlock(pts.pt_gate);
435: return (pts.pt_rval);
436: }
437:
438: /*
439: * This routine is called when a child that is being traced receives a signal
440: * that is not caught or ignored. It follows up on any requests by the parent
441: * and returns when done.
442: */
443: ptret()
444: {
445: register PROC *pp;
446: register PROC *pp1;
447: register int sign;
448: unsigned off;
449:
450: pp = SELF;
451: next:
452: u.u_error = 0;
453: if (pp->p_ppid == 1)
454: return (SIGKILL);
455: sign = -1;
456: lock(pnxgate);
457: pp1 = &procq;
458: for (;;) {
459: if ((pp1=pp1->p_nforw) == &procq) {
460: sign = SIGKILL;
461: break;
462: }
463: if (pp1->p_pid != pp->p_ppid)
464: continue;
465: if (pp1->p_state == PSSLEEP)
466: wakeup((char *)pp1);
467: break;
468: }
469: unlock(pnxgate);
470: while (sign < 0) {
471: if (pts.pt_busy==0 || pp->p_pid!=pts.pt_pid) {
472: v_sleep((char *)&pts.pt_req, CVPTRET, IVPTRET, SVPTRET, "ptret");
473: /* Something about signals to a traced child. */
474: goto next;
475: }
476: switch (pts.pt_req) {
477: case 1:
478: if (XMODE_286) {
479: pts.pt_rval = getuwd(NBPS+pts.pt_addr);
480: break;
481: }
482: case 2:
483: pts.pt_rval = getuwd(pts.pt_addr);
484: break;
485: case 3:
486: off = (unsigned)pts.pt_addr;
487: if (off < UPASIZE)
488: pts.pt_rval = *(int *)((char *)&u+off);
489: else
490: u.u_error = EINVAL;
491: break;
492: case 4:
493: if (XMODE_286) {
494: putuwd(NBPS+pts.pt_addr, pts.pt_data);
495: break;
496: }
497: case 5:
498: putuwd(pts.pt_addr, pts.pt_data);
499: break;
500: case 6:
501: if (msetuof(pts.pt_addr, pts.pt_data) == 0)
502: u.u_error = EINVAL;
503: break;
504: case 7:
505: goto sig;
506: case 8:
507: sign = SIGKILL;
508: break;
509: case 9:
510: msigsin();
511: sig:
512: if (pts.pt_data<0 || pts.pt_data>NSIG) {
513: u.u_error = EINVAL;
514: break;
515: }
516: sign = pts.pt_data;
517: if (pts.pt_addr != SIG_IGN)
518: msetppc((vaddr_t)pts.pt_addr);
519: break;
520: default:
521: u.u_error = EINVAL;
522: }
523: if ((pts.pt_errs=u.u_error) == EFAULT)
524: pts.pt_errs = EINVAL;
525: pts.pt_busy = 0;
526: wakeup((char *)&pts.pt_busy);
527: }
528: return (sign);
529: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.