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