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