cntrlc.cc
Go to the documentation of this file.
1 /****************************************
2 * Computer Algebra System SINGULAR *
3 ****************************************/
4 /*
5 * ABSTRACT - interupt handling
6 */
7 #include <stdio.h>
8 #include <stddef.h>
9 #include <stdlib.h>
10 #include <strings.h>
11 #include <signal.h>
12 #include <sys/types.h>
13 #include <sys/wait.h>
14 
15 #include <kernel/mod2.h>
16 
17 #include <omalloc/omalloc.h>
18 
19 #include <reporter/si_signals.h>
20 #include <Singular/fevoices.h>
21 
22 #include <Singular/tok.h>
23 #include <Singular/ipshell.h>
24 #include <Singular/cntrlc.h>
25 #include <Singular/feOpt.h>
26 #include <Singular/misc_ip.h>
27 #include <Singular/links/silink.h>
28 #include <Singular/links/ssiLink.h>
29 
30 /* undef, if you don't want GDB to come up on error */
31 
32 #define CALL_GDB
33 
34 #if defined(__OPTIMIZE__) && defined(CALL_GDB)
35 #undef CALL_GDB
36 #endif
37 
38 #if defined(unix)
39  #include <unistd.h>
40  #include <sys/types.h>
41 
42  #ifdef TIME_WITH_SYS_TIME
43  #include <time.h>
44  #ifdef HAVE_SYS_TIME_H
45  #include <sys/time.h>
46  #endif
47  #else
48  #ifdef HAVE_SYS_TIME_H
49  #include <sys/time.h>
50  #else
51  #include <time.h>
52  #endif
53  #endif
54  #ifdef HAVE_SYS_TIMES_H
55  #include <sys/times.h>
56  #endif
57 
58  #define INTERACTIVE 0
59  #define STACK_TRACE 1
60 
61  #ifdef CALL_GDB
62  static void debug (int);
63  static void debug_stop (char *const*args);
64  #endif
65  #ifndef __OPTIMIZE__
66  static void stack_trace_sigchld (int);
67  static void stack_trace (char *const*args);
68  #endif
69 #endif
70 
73 
74 void sig_pipe_hdl(int /*sig*/)
75 {
76  if (pipeLastLink!=NULL)
77  {
80  WerrorS("pipe failed");
81  }
82 }
83 
85 volatile int defer_shutdown = 0;
86 
87 void sig_term_hdl(int /*sig*/)
88 {
89  do_shutdown = TRUE;
90  if (!defer_shutdown)
91  {
92  m2_end(1);
93  }
94 }
95 
96 /*---------------------------------------------------------------------*
97  * File scope Variables (Variables share by several functions in
98  * the same file )
99  *
100  *---------------------------------------------------------------------*/
101 /* data */
104 short si_restart=0;
106 
107 typedef void (*si_hdl_typ)(int);
108 
109 
110 /*0 implementation*/
111 /*---------------------------------------------------------------------*
112  * Functions declarations
113  *
114  *---------------------------------------------------------------------*/
115 void sigint_handler(int /*sig*/);
116 
117 si_hdl_typ si_set_signal ( int sig, si_hdl_typ signal_handler);
118 
119 /*---------------------------------------------------------------------*/
120 /**
121  * @brief meta function for binding a signal to an handler
122 
123  @param[in] sig Signal number
124  @param[in] signal_handler Pointer to signal handler
125 
126  @return value of signal()
127 **/
128 /*---------------------------------------------------------------------*/
129 si_hdl_typ si_set_signal ( int sig, si_hdl_typ signal_handler)
130 {
131 #if 0
132  si_hdl_typ retval=signal (sig, (si_hdl_typ)signal_handler);
133  if (retval == SIG_ERR)
134  {
135  fprintf(stderr, "Unable to init signal %d ... exiting...\n", sig);
136  }
137  si_siginterrupt(sig, 0);
138  /*system calls will be restarted if interrupted by the specified
139  * signal sig. This is the default behavior in Linux.
140  */
141 #else
142  struct sigaction new_action,old_action;
143  memset(&new_action, 0, sizeof(struct sigaction));
144 
145  /* Set up the structure to specify the new action. */
146  new_action.sa_handler = signal_handler;
147  if (sig==SIGINT)
148  sigemptyset (&new_action.sa_mask);
149  else
150  new_action.sa_flags = SA_RESTART;
151 
152  int r=si_sigaction (sig, &new_action, &old_action);
153  si_hdl_typ retval=(si_hdl_typ)old_action.sa_handler;
154  if (r == -1)
155  {
156  fprintf(stderr, "Unable to init signal %d ... exiting...\n", sig);
157  retval=SIG_ERR;
158  }
159 #endif
160  return retval;
161 } /* si_set_signal */
162 
163 
164 /*---------------------------------------------------------------------*/
165 #if defined(__linux__) && defined(__i386)
166  #if !defined(HAVE_SIGCONTEXT) && !defined(HAVE_ASM_SIGCONTEXT_H)
167 // we need the following structure sigcontext_struct.
168 // if configure finds asm/singcontext.h we assume
169 // that this file contains the structure and is included
170 // via signal.h
171 struct sigcontext_struct {
172  unsigned short gs, __gsh;
173  unsigned short fs, __fsh;
174  unsigned short es, __esh;
175  unsigned short ds, __dsh;
176  unsigned long edi;
177  unsigned long esi;
178  unsigned long ebp;
179  unsigned long esp;
180  unsigned long ebx;
181  unsigned long edx;
182  unsigned long ecx;
183  unsigned long eax;
184  unsigned long trapno;
185  unsigned long err;
186  unsigned long eip;
187  unsigned short cs, __csh;
188  unsigned long eflags;
189  unsigned long esp_at_signal;
190  unsigned short ss, __ssh;
191  unsigned long i387;
192  unsigned long oldmask;
193  unsigned long cr2;
194 };
195 #endif
196 #define HAVE_SIGSTRUCT
197 typedef struct sigcontext_struct sigcontext;
198 #endif
199 
200 #if defined(__linux__) && defined(__amd64)
201 #define HAVE_SIGSTRUCT
202 #endif
203 
204 
205 #if defined(HAVE_SIGSTRUCT)
206 /*2---------------------------------------------------------------------*/
207 /**
208  * @brief signal handler for run time errors, linux/i386, x86_64 version
209 
210  @param[in] sig
211  @param[in] s
212 **/
213 /*---------------------------------------------------------------------*/
214 void sigsegv_handler(int sig, sigcontext s)
215 {
216  fprintf(stderr,"Singular : signal %d (v: %d):\n",sig,SINGULAR_VERSION);
217  if (sig!=SIGINT)
218  {
219  fprintf(stderr,"current line:>>%s<<\n",my_yylinebuf);
220  fprintf(stderr,"Segment fault/Bus error occurred at %lx because of %lx (r:%d)\n"
221  "please inform the authors\n",
222  #ifdef __i386__
223  (long)s.eip,
224  #else /* x86_64*/
225  (long)s.rip,
226  #endif
227  (long)s.cr2,siRandomStart);
228  }
229 #ifdef __OPTIMIZE__
230  if(si_restart<3)
231  {
232  si_restart++;
233  fprintf(stderr,"trying to restart...\n");
234  init_signals();
235  longjmp(si_start_jmpbuf,1);
236  }
237 #endif /* __OPTIMIZE__ */
238 #ifdef CALL_GDB
239  if (sig!=SIGINT)
240  {
241  if (singular_in_batchmode) debug(STACK_TRACE);
242  else debug(INTERACTIVE);
243  }
244 #endif /* CALL_GDB */
245  exit(0);
246 }
247 
248 /*---------------------------------------------------------------------*/
249 #elif defined(SunOS) /*SPARC_SUNOS*/
250 /*2
251 * signal handler for run time errors, sparc sunos 4 version
252 */
253 void sigsegv_handler(int sig, int code, struct sigcontext *scp, char *addr)
254 {
255  fprintf(stderr,"Singular : signal %d, code %d (v: %d):\n",
256  sig,code,SINGULAR_VERSION);
257  if ((sig!=SIGINT)&&(sig!=SIGABRT))
258  {
259  fprintf(stderr,"current line:>>%s<<\n",my_yylinebuf);
260  fprintf(stderr,"Segment fault/Bus error occurred at %x (r:%d)\n"
261  "please inform the authors\n",
262  (int)addr,siRandomStart);
263  }
264 #ifdef __OPTIMIZE__
265  if(si_restart<3)
266  {
267  si_restart++;
268  fprintf(stderr,"trying to restart...\n");
269  init_signals();
270  longjmp(si_start_jmpbuf,1);
271  }
272 #endif /* __OPTIMIZE__ */
273 #ifdef CALL_GDB
274  if (sig!=SIGINT) debug(STACK_TRACE);
275 #endif /* CALL_GDB */
276  exit(0);
277 }
278 
279 #else
280 
281 /*---------------------------------------------------------------------*/
282 /*2
283 * signal handler for run time errors, general version
284 */
285 void sigsegv_handler(int sig)
286 {
287  fprintf(stderr,"Singular : signal %d (v: %d):\n",
288  sig,SINGULAR_VERSION);
289  if (sig!=SIGINT)
290  {
291  fprintf(stderr,"current line:>>%s<<\n",my_yylinebuf);
292  fprintf(stderr,"Segment fault/Bus error occurred (r:%d)\n"
293  "please inform the authors\n",
294  siRandomStart);
295  }
296  #ifdef __OPTIMIZE__
297  if(si_restart<3)
298  {
299  si_restart++;
300  fprintf(stderr,"trying to restart...\n");
301  init_signals();
302  longjmp(si_start_jmpbuf,1);
303  }
304  #endif /* __OPTIMIZE__ */
305  #if defined(unix)
306  #ifdef CALL_GDB
307  if (sig!=SIGINT) debug(STACK_TRACE);
308  #endif /* CALL_GDB */
309  #endif /* unix */
310  exit(0);
311 }
312 #endif
313 
314 
315 /*2
316 * signal handler for SIGINT
317 */
319 void sigint_handler(int /*sig*/)
320 {
321  mflush();
322  #ifdef HAVE_FEREAD
324  #endif /* HAVE_FEREAD */
325  char default_opt=' ';
326  if ((feOptSpec[FE_OPT_CNTRLC].value!=NULL)
327  && ((char*)(feOptSpec[FE_OPT_CNTRLC].value))[0])
328  { default_opt=((char*)(feOptSpec[FE_OPT_CNTRLC].value))[0]; }
329  loop
330  {
331  int cnt=0;
332  int c;
333 
335  {
336  c = 'q';
337  }
338  else if (default_opt!=' ')
339  {
340  c = default_opt;
341  }
342  else
343  {
344  fprintf(stderr,"// ** Interrupt at cmd:`%s` in line:'%s'\n",
346  if (feOptValue(FE_OPT_EMACS) == NULL)
347  {
348  fputs("abort after this command(a), abort immediately(r), print backtrace(b), continue(c) or quit Singular(q) ?",stderr);
349  fflush(stderr);fflush(stdin);
350  c = fgetc(stdin);
351  }
352  else
353  {
354  c = 'a';
355  }
356  }
357 
358  switch(c)
359  {
360  case 'q': case EOF:
361  m2_end(2);
362  case 'r':
363  if (sigint_handler_cnt<3)
364  {
366  fputs("** Warning: Singular should be restarted as soon as possible **\n",stderr);
367  fflush(stderr);
368  extern void my_yy_flush();
369  my_yy_flush();
371  longjmp(si_start_jmpbuf,1);
372  }
373  else
374  {
375  fputs("** tried too often, try another possibility **\n",stderr);
376  fflush(stderr);
377  }
378  break;
379  case 'b':
380  VoiceBackTrack();
381  break;
382  case 'a':
383  siCntrlc++;
384  case 'c':
385  if ((feOptValue(FE_OPT_EMACS) == NULL) && (default_opt!=' '))
386  {
387  /* Read until a newline or EOF */
388  while (c != EOF && c != '\n') c = fgetc(stdin);
389  }
391  return;
392  //siCntrlc ++;
393  //if (siCntrlc>2) si_set_signal(SIGINT,(si_hdl_typ) sigsegv_handler);
394  //else si_set_signal(SIGINT,(si_hdl_typ) sigint_handler);
395  }
396  cnt++;
397  if(cnt>5) m2_end(2);
398  }
399 }
400 
401 //void test_int()
402 //{
403 // if (siCntrlc!=0)
404 // {
405 // int saveecho = si_echo;
406 // siCntrlc = FALSE;
407 // si_set_signal(SIGINT ,sigint_handler);
408 // iiDebug();
409 // si_echo = saveecho;
410 // }
411 //}
412 
413 #ifdef unix
414 # ifndef __OPTIMIZE__
415 volatile int si_stop_stack_trace_x;
416 # ifdef CALL_GDB
417 static void debug (int method)
418 {
419  if (feOptValue(FE_OPT_NO_TTY))
420  {
421  dReportError("Caught Signal 11");
422  return;
423  }
424  int pid;
425  char buf[16];
426  char * args[4] = { (char*)"gdb", (char*)"Singular", NULL, NULL };
427 
428  #ifdef HAVE_FEREAD
430  #endif /* HAVE_FEREAD */
431 
432  sprintf (buf, "%d", getpid ());
433 
434  args[2] = buf;
435 
436  pid = fork ();
437  if (pid == 0)
438  {
439  switch (method)
440  {
441  case INTERACTIVE:
442  fprintf (stderr, "\n\nquit with \"p si_stop_stack_trace_x=0\"\n\n\n");
443  debug_stop (args);
444  break;
445  case STACK_TRACE:
446  fprintf (stderr, "stack_trace\n");
447  stack_trace (args);
448  break;
449  default:
450  // should not be reached:
451  exit(1);
452  }
453  }
454  else if (pid == -1)
455  {
456  perror ("could not fork");
457  return;
458  }
459 
460  si_stop_stack_trace_x = 1;
461  while (si_stop_stack_trace_x) ;
462 }
463 
464 static void debug_stop (char *const*args)
465 {
466  execvp (args[0], args);
467  perror ("exec failed");
468  _exit (0);
469 }
470 # endif /* CALL_GDB */
471 
472 static void stack_trace (char *const*args)
473 {
474  int pid;
475  int in_fd[2];
476  int out_fd[2];
477  fd_set fdset;
478  fd_set readset;
479  struct timeval tv;
480  int sel, index, state;
481  char buffer[256];
482  char c;
483 
484  if ((pipe (in_fd) == -1) || (pipe (out_fd) == -1))
485  {
486  perror ("could open pipe");
487  m2_end(999);
488  }
489 
490  pid = fork ();
491  if (pid == 0)
492  {
493  si_close (0); si_dup2 (in_fd[0],0); /* set the stdin to the in pipe */
494  si_close (1); si_dup2 (out_fd[1],1); /* set the stdout to the out pipe */
495  si_close (2); si_dup2 (out_fd[1],2); /* set the stderr to the out pipe */
496 
497  execvp (args[0], args); /* exec gdb */
498  perror ("exec failed");
499  m2_end(999);
500  }
501  else if (pid == -1)
502  {
503  perror ("could not fork");
504  m2_end(999);
505  }
506 
507  FD_ZERO (&fdset);
508  FD_SET (out_fd[0], &fdset);
509 
510  si_write (in_fd[1], "backtrace\n", 10);
511  si_write (in_fd[1], "p si_stop_stack_trace_x = 0\n", 28);
512  si_write (in_fd[1], "quit\n", 5);
513 
514  index = 0;
515  state = 0;
516 
517  loop
518  {
519  readset = fdset;
520  tv.tv_sec = 1;
521  tv.tv_usec = 0;
522 
523  sel = si_select (FD_SETSIZE, &readset, NULL, NULL, &tv);
524  if (sel == -1)
525  break;
526 
527  if ((sel > 0) && (FD_ISSET (out_fd[0], &readset)))
528  {
529  if (si_read (out_fd[0], &c, 1))
530  {
531  switch (state)
532  {
533  case 0:
534  if (c == '#')
535  {
536  state = 1;
537  index = 0;
538  buffer[index++] = c;
539  }
540  break;
541  case 1:
542  buffer[index++] = c;
543  if ((c == '\n') || (c == '\r'))
544  {
545  buffer[index] = 0;
546  fprintf (stderr, "%s", buffer);
547  state = 0;
548  index = 0;
549  }
550  break;
551  default:
552  break;
553  }
554  }
555  }
556  else if (si_stop_stack_trace_x==0)
557  break;
558  }
559 
560  si_close (in_fd[0]);
561  si_close (in_fd[1]);
562  si_close (out_fd[0]);
563  si_close (out_fd[1]);
564  m2_end(0);
565 }
566 
567 # endif /* !__OPTIMIZE__ */
568 #endif /* unix */
569 
570 /*2
571 * init signal handlers
572 */
574 {
575  #ifdef SIGSEGV
577  #endif
578  #ifdef SIGBUS
579  si_set_signal(SIGBUS, (si_hdl_typ)sigsegv_handler);
580  #endif
581  #ifdef SIGFPE
582  si_set_signal(SIGFPE, (si_hdl_typ)sigsegv_handler);
583  #endif
584  #ifdef SIGILL
585  si_set_signal(SIGILL, (si_hdl_typ)sigsegv_handler);
586  #endif
587  #ifdef SIGIOT
588  si_set_signal(SIGIOT, (si_hdl_typ)sigsegv_handler);
589  #endif
594 }
595 
jmp_buf si_start_jmpbuf
Definition: cntrlc.cc:102
void VoiceBackTrack()
Definition: fevoices.cc:77
const CanonicalForm int s
Definition: facAbsFact.cc:55
This file provides miscellaneous functionality.
void sigint_handler(int)
Definition: cntrlc.cc:319
si_link pipeLastLink
Definition: cntrlc.cc:71
static void * feOptValue(feOptIndex opt)
Definition: feOpt.h:40
loop
Definition: myNF.cc:98
if(0 > strat->sl)
Definition: myNF.cc:73
#define FALSE
Definition: auxiliary.h:95
BOOLEAN fe_is_raw_tty
Definition: fereadl.c:75
#define SINGULAR_VERSION
Definition: mod2.h:92
void sig_term_hdl(int)
Definition: cntrlc.cc:87
void m2_end(int i)
Definition: misc_ip.cc:1072
int siRandomStart
Definition: cntrlc.cc:103
char buffer[1024]
Definition: run.c:54
#define TRUE
Definition: auxiliary.h:99
void WerrorS(const char *s)
Definition: feFopen.cc:24
#define mflush()
Definition: reporter.h:57
int sigint_handler_cnt
Definition: cntrlc.cc:318
char my_yylinebuf[80]
Definition: febase.cc:48
const ring r
Definition: syzextra.cc:208
BOOLEAN singular_in_batchmode
Definition: cntrlc.cc:72
volatile BOOLEAN do_shutdown
Definition: cntrlc.cc:84
Voice * feInitStdin(Voice *pp)
Definition: fevoices.cc:661
BOOLEAN siCntrlc
Definition: cntrlc.cc:105
int status int void * buf
Definition: si_signals.h:59
void(* si_hdl_typ)(int)
Definition: cntrlc.cc:107
void sigsegv_handler(int sig)
Definition: cntrlc.cc:285
si_hdl_typ si_set_signal(int sig, si_hdl_typ signal_handler)
meta function for binding a signal to an handler
Definition: cntrlc.cc:129
struct fe_option feOptSpec[]
void sig_pipe_hdl(int)
Definition: cntrlc.cc:74
short si_restart
Definition: cntrlc.cc:104
static int index(p_Length length, p_Ord ord)
Definition: p_Procs_Impl.h:592
#define NULL
Definition: omList.c:10
const char * Tok2Cmdname(int tok)
Definition: gentable.cc:130
Voice * currentVoice
Definition: fevoices.cc:57
void init_signals()
Definition: cntrlc.cc:573
#define si_siginterrupt(arg1, arg2)
volatile int defer_shutdown
Definition: cntrlc.cc:85
void fe_temp_reset(void)
Definition: fereadl.c:113
int dReportError(const char *fmt,...)
Definition: dError.cc:45
void my_yy_flush()
Definition: scanner.cc:2333
int iiOp
Definition: iparith.cc:227
int BOOLEAN
Definition: auxiliary.h:86