1 /**********
2 Copyright 1990 Regents of the University of California. All rights reserved.
3 Author: 1985 Wayne A. Christopher, U. C. Berkeley CAD Group
4 **********/
5
6 /*
7 * The signal routines for spice 3 and nutmeg.
8 */
9
10 #include "ngspice/ngspice.h"
11 #include "ngspice/ifsim.h"
12 #include "ngspice/iferrmsg.h"
13 #include "ngspice/cpdefs.h"
14 #include "ngspice/ftedefs.h"
15 #include "ngspice/ftedev.h"
16 #include <setjmp.h>
17 #include <signal.h>
18 #include "signal_handler.h"
19 #include "plotting/graf.h"
20
21 #ifdef HAS_WINGUI
22 void winmessage(char* new_msg);
23 #endif
24
25 #ifdef HAVE_GNUREADLINE
26 /* Added GNU Readline Support 11/3/97 -- Andrew Veliath <veliaa@rpi.edu> */
27 /* from spice3f4 patch to ng-spice. jmr */
28 #include <readline/readline.h>
29 #include <readline/history.h>
30 #endif
31
32 #ifdef HAVE_BSDEDITLINE
33 /* SJB added edit line support 2005-05-05 */
34 #include <editline/readline.h>
35 #endif /* HAVE_BSDEDITLINE */
36
37 JMP_BUF jbuf;
38
39 /* The (void) signal handlers... SIGINT is the only one that gets reset (by
40 * cshpar) so it is global. They are ifdef BSD because of the sigmask
41 * stuff in sigstop. We set the interrupt flag and return if ft_setflag
42 * is TRUE.
43 */
44
45
46 /* The purpose of ft_sigintr_cleanup() is to handle all processing of asynchronous
47 * signals which require user process context. Some kernel services are not
48 * allowed to be called from asynchronous signal handlers. (e.g. mutexes)
49 */
50
51 void
ft_sigintr_cleanup(void)52 ft_sigintr_cleanup(void)
53 {
54 gr_clean(); /* Clean up plot window */
55
56 /* sjb - what to do for editline???
57 The following are not supported in editline */
58 #if defined(HAVE_GNUREADLINE)
59 /* Clean up readline after catching signals */
60 /* One or all of these might be superfluous */
61 (void) rl_free_line_state();
62 (void) rl_cleanup_after_signal();
63 (void) rl_reset_after_signal();
64 #endif /* defined(HAVE_GNUREADLINE) || defined(HAVE_BSDEDITLINE) */
65
66 /* To restore screen after an interrupt to a plot for instance */
67 cp_interactive = TRUE;
68 cp_resetcontrol(TRUE);
69 }
70
71
72 /* invoke this function upon keyboard interrupt */
73 RETSIGTYPE
ft_sigintr(void)74 ft_sigintr(void)
75 {
76 static int interrupt_counter = 0;
77
78 /* fprintf(cp_err, "Received interrupt. Handling it . . . . .\n"); */
79
80 /* Reinstall ft_signintr as the signal handler. */
81 (void) signal(SIGINT, (SIGNAL_FUNCTION) ft_sigintr);
82
83 if (ft_intrpt) { /* check to see if we're being interrupted repeatedly */
84 fprintf(cp_err, "\nInterrupted again (ouch)\n");
85 interrupt_counter++;
86 } else {
87 fprintf(cp_err, "\nInterrupted once . . .\n");
88 ft_intrpt = TRUE;
89 interrupt_counter = 1;
90 }
91
92 if (interrupt_counter >= 3) {
93 fprintf(cp_err, "\nKilling, since %d interrupts have been requested\n\n", interrupt_counter);
94 controlled_exit(1);
95 }
96
97 if (ft_setflag) {
98 return; /* just return without aborting simulation if ft_setflag = TRUE */
99 }
100
101 /* here we jump to the start of command processing in main() after resetting everything. */
102 LONGJMP(jbuf, 1);
103 }
104
105
106 RETSIGTYPE
sigfloat(int code)107 sigfloat(int code)
108 {
109 fperror("Error", code);
110 rewind(cp_out);
111 (void) signal(SIGFPE, (SIGNAL_FUNCTION) sigfloat);
112 LONGJMP(jbuf, 1);
113 }
114
115
116 /* This should give a new prompt if cshpar is waiting for input. */
117
118 #ifdef SIGTSTP
119
120 RETSIGTYPE
sigstop(void)121 sigstop(void)
122 {
123 gr_clean();
124 cp_ccon(FALSE);
125 (void) signal(SIGTSTP, SIG_DFL);
126 (void) kill(getpid(), SIGTSTP); /* This should stop us */
127 }
128
129
130 RETSIGTYPE
sigcont(void)131 sigcont(void)
132 {
133 (void) signal(SIGTSTP, (SIGNAL_FUNCTION) sigstop);
134 if (cp_cwait)
135 LONGJMP(jbuf, 1);
136 }
137
138
139 #endif
140
141
142 /* Special (void) signal handlers. */
143
144 RETSIGTYPE
sigill(void)145 sigill(void)
146 {
147 fprintf(cp_err, "\ninternal error -- illegal instruction\n");
148 fatal();
149 }
150
151
152 RETSIGTYPE
sigbus(void)153 sigbus(void)
154 {
155 fprintf(cp_err, "\ninternal error -- bus error\n");
156 fatal();
157 }
158
159
160 RETSIGTYPE
sigsegv(void)161 sigsegv(void)
162 {
163 fprintf(cp_err, "\ninternal error -- segmentation violation\n");
164 #ifdef HAS_WINGUI
165 winmessage("Fatal error in NGSPICE");
166 #endif
167 fatal();
168 }
169
170 RETSIGTYPE
sigsegvsh(void)171 sigsegvsh(void)
172 {
173 fprintf(cp_err, "\ninternal error -- segmentation violation\n");
174 controlled_exit(EXIT_SEGV);
175 }
176
177
178 RETSIGTYPE
sig_sys(void)179 sig_sys(void)
180 {
181 fprintf(cp_err, "\ninternal error -- bad argument to system call\n");
182 fatal();
183 }
184