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