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