source: git/Singular/cntrlc.cc @ 1b2216

spielwiese
Last change on this file since 1b2216 was ccae2f, checked in by Hans Schoenemann <hannes@…>, 11 years ago
fix: simplified crash handling for Singularg from master
  • Property mode set to 100644
File size: 14.1 KB
Line 
1/****************************************
2*  Computer Algebra System SINGULAR     *
3****************************************/
4/*
5* ABSTRACT - interupt handling
6*/
7
8/* includes */
9#ifdef DecAlpha_OSF1
10#define _XOPEN_SOURCE_EXTENDED
11#endif /* MP3-Y2 0.022UF */
12
13#include <stdio.h>
14#include <stddef.h>
15#include <stdlib.h>
16#include <strings.h>
17#include <signal.h>
18#include <sys/types.h>
19#include <sys/wait.h>
20
21#include "config.h"
22#include <kernel/mod2.h>
23#include <omalloc/omalloc.h>
24
25#include <kernel/polys.h>
26#include <kernel/febase.h>
27void sig_chld_hdl(int sig); /*#include <Singular/links/ssiLink.h>*/
28//#include <Singular/feOpt.h>
29//#include <Singular/version.h>
30//#include <Singular/silink.h>
31//#include <Singular/ssiLink.h>
32#include <Singular/si_signals.h>
33
34#include "tok.h"
35#include "ipshell.h"
36#include "cntrlc.h"
37#include "feOpt.h"
38#include "version.h"
39#include "links/silink.h"
40
41/* undef, if you don't want GDB to come up on error */
42
43#if defined(__OPTIMIZE__) && defined(CALL_GDB)
44#undef CALL_GDB
45#endif
46
47#if defined(unix)
48 #include <unistd.h>
49 #include <sys/types.h>
50
51 #ifdef TIME_WITH_SYS_TIME
52   #include <time.h>
53   #ifdef HAVE_SYS_TIME_H
54     #include <sys/time.h>
55   #endif
56 #else
57   #ifdef HAVE_SYS_TIME_H
58     #include <sys/time.h>
59   #else
60     #include <time.h>
61   #endif
62 #endif
63 #ifdef HAVE_SYS_TIMES_H
64   #include <sys/times.h>
65 #endif
66
67 #define INTERACTIVE 0
68 #define STACK_TRACE 1
69
70 #ifdef CALL_GDB
71   static void debug (int);
72   static void debug_stop (char *const*args);
73 #endif
74 #ifndef __OPTIMIZE__
75   static void stack_trace_sigchld (int);
76   static void stack_trace (char *const*args);
77 #endif
78#endif
79
80si_link pipeLastLink=NULL;
81BOOLEAN singular_in_batchmode=FALSE;
82
83void sig_pipe_hdl(int /*sig*/)
84{
85 if (pipeLastLink!=NULL)
86 {
87   slClose(pipeLastLink);
88   pipeLastLink=NULL;
89   WerrorS("pipe failed");
90 }
91}
92
93void sig_term_hdl(int /*sig*/)
94{
95 while (ssiToBeClosed!=NULL)
96 {
97   slClose(ssiToBeClosed->l);
98   if (ssiToBeClosed==NULL) break;
99   ssiToBeClosed=(link_list)ssiToBeClosed->next;
100 }
101 exit(1);
102}
103
104/*---------------------------------------------------------------------*
105 * File scope Variables (Variables share by several functions in
106 *                       the same file )
107 *
108 *---------------------------------------------------------------------*/
109/* data */
110jmp_buf si_start_jmpbuf;
111int siRandomStart;
112short si_restart=0;
113BOOLEAN siCntrlc = FALSE;
114
115typedef void (*si_hdl_typ)(int);
116
117
118/*0 implementation*/
119/*---------------------------------------------------------------------*
120 * Functions declarations
121 *
122 *---------------------------------------------------------------------*/
123void sigint_handler(int sig);
124
125si_hdl_typ si_set_signal ( int sig, si_hdl_typ signal_handler);
126
127/*---------------------------------------------------------------------*/
128/**
129 * @brief meta function for binding a signal to an handler
130
131 @param[in] sig             Signal number
132 @param[in] signal_handler  Pointer to signal handler
133
134 @return value of signal()
135**/
136/*---------------------------------------------------------------------*/
137si_hdl_typ si_set_signal ( int sig, si_hdl_typ signal_handler)
138{
139#if 0
140  si_hdl_typ retval=signal (sig, (si_hdl_typ)signal_handler);
141  if (retval == SIG_ERR)
142  {
143     fprintf(stderr, "Unable to init signal %d ... exiting...\n", sig);
144  }
145  si_siginterrupt(sig, 0);
146  /*system calls will be restarted if interrupted by  the  specified
147   * signal sig.  This is the default behavior in Linux.
148   */
149#else
150  struct sigaction new_action,old_action;
151
152  /* Set up the structure to specify the new action. */
153  new_action.sa_handler = signal_handler;
154  if (sig==SIGINT)
155    sigemptyset (&new_action.sa_mask);
156  else
157    new_action.sa_flags = SA_RESTART;
158
159  int r=si_sigaction (sig, &new_action, &old_action);
160  si_hdl_typ retval=(si_hdl_typ)old_action.sa_handler;
161  if (r == -1)
162  {
163     fprintf(stderr, "Unable to init signal %d ... exiting...\n", sig);
164     retval=SIG_ERR;
165  }
166#endif
167  return retval;
168}                               /* si_set_signal */
169
170
171/*---------------------------------------------------------------------*/
172#if defined(ix86_Linux)
173  #if !defined(HAVE_SIGCONTEXT) && !defined(HAVE_ASM_SIGCONTEXT_H)
174// we need the following structure sigcontext_struct.
175// if configure finds asm/singcontext.h we assume
176// that this file contains the structure and is included
177// via signal.h
178struct sigcontext_struct {
179        unsigned short gs, __gsh;
180        unsigned short fs, __fsh;
181        unsigned short es, __esh;
182        unsigned short ds, __dsh;
183        unsigned long edi;
184        unsigned long esi;
185        unsigned long ebp;
186        unsigned long esp;
187        unsigned long ebx;
188        unsigned long edx;
189        unsigned long ecx;
190        unsigned long eax;
191        unsigned long trapno;
192        unsigned long err;
193        unsigned long eip;
194        unsigned short cs, __csh;
195        unsigned long eflags;
196        unsigned long esp_at_signal;
197        unsigned short ss, __ssh;
198        unsigned long i387;
199        unsigned long oldmask;
200        unsigned long cr2;
201};
202#endif
203#define HAVE_SIGSTRUCT
204typedef struct sigcontext_struct sigcontext;
205#endif
206
207#if defined(x86_64_Linux)
208#define HAVE_SIGSTRUCT
209#endif
210
211
212#if defined(HAVE_SIGSTRUCT)
213/*2---------------------------------------------------------------------*/
214/**
215 * @brief signal handler for run time errors, linux/i386, x86_64 version
216
217 @param[in] sig
218 @param[in] s
219**/
220/*---------------------------------------------------------------------*/
221void sigsegv_handler(int sig, sigcontext s)
222{
223  fprintf(stderr,"Singular : signal %d (v: %d/%s):\n",sig,SINGULAR_VERSION,feVersionId);
224  if (sig!=SIGINT)
225  {
226    fprintf(stderr,"current line:>>%s<<\n",my_yylinebuf);
227    fprintf(stderr,"Segment fault/Bus error occurred at %lx because of %lx (r:%d)\n"
228                   "please inform the authors\n",
229                   #ifdef __i386__
230                   (long)s.eip,
231                   #else /* x86_64*/
232                   (long)s.rip,
233                   #endif
234                   (long)s.cr2,siRandomStart);
235  }
236#ifdef __OPTIMIZE__
237  if(si_restart<3)
238  {
239    si_restart++;
240    fprintf(stderr,"trying to restart...\n");
241    init_signals();
242    longjmp(si_start_jmpbuf,1);
243  }
244#endif /* __OPTIMIZE__ */
245#ifdef CALL_GDB
246  if (sig!=SIGINT)
247  {
248    if (singular_in_batchmode) debug(STACK_TRACE);
249    else                       debug(INTERACTIVE);
250  }
251#endif /* CALL_GDB */
252  exit(0);
253}
254
255/*---------------------------------------------------------------------*/
256#elif defined(SunOS) /*SPARC_SUNOS*/
257/*2
258* signal handler for run time errors, sparc sunos 4 version
259*/
260void sigsegv_handler(int sig, int code, struct sigcontext *scp, char *addr)
261{
262  fprintf(stderr,"Singular : signal %d, code %d (v: %d/%s):\n",
263    sig,code,SINGULAR_VERSION,feVersionId);
264  if ((sig!=SIGINT)&&(sig!=SIGABRT))
265  {
266    fprintf(stderr,"current line:>>%s<<\n",my_yylinebuf);
267    fprintf(stderr,"Segment fault/Bus error occurred at %x (r:%d)\n"
268                   "please inform the authors\n",
269                   (int)addr,siRandomStart);
270  }
271#ifdef __OPTIMIZE__
272  if(si_restart<3)
273  {
274    si_restart++;
275    fprintf(stderr,"trying to restart...\n");
276    init_signals();
277    longjmp(si_start_jmpbuf,1);
278  }
279#endif /* __OPTIMIZE__ */
280#ifdef CALL_GDB
281  if (sig!=SIGINT) debug(STACK_TRACE);
282#endif /* CALL_GDB */
283  exit(0);
284}
285#else
286
287/*---------------------------------------------------------------------*/
288/*2
289* signal handler for run time errors, general version
290*/
291void sigsegv_handler(int sig)
292{
293  fprintf(stderr,"Singular : signal %d (v: %d/%s):\n",
294    sig,SINGULAR_VERSION,feVersionId);
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  /* debug(..) does not work under HPUX (because ptrace does not work..) */
313  #ifdef CALL_GDB
314  if (sig!=SIGINT) debug(STACK_TRACE);
315  #endif /* CALL_GDB */
316  #endif /* unix */
317  exit(0);
318}
319#endif
320
321/*2
322* signal handler for SIGINT
323*/
324int sigint_handler_cnt=0;
325void sigint_handler(int /*sig*/)
326{
327  mflush();
328  #ifdef HAVE_FEREAD
329  if (fe_is_raw_tty) fe_temp_reset();
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
340    if (singular_in_batchmode)
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",
351        Tok2Cmdname(iiOp),my_yylinebuf);
352      if (feGetOptValue(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 ((feGetOptValue(FE_OPT_EMACS) == NULL) && (default_opt!=' '))
388                {
389                  /* Read until a newline or EOF */
390                  while (c != EOF && c != '\n') c = fgetc(stdin);
391                }
392                si_set_signal(SIGINT ,(si_hdl_typ)sigint_handler);
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__
417volatile int si_stop_stack_trace_x;
418#    ifdef CALL_GDB
419static 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*)"Singularg", NULL, NULL };
429
430  #ifdef HAVE_FEREAD
431  if (fe_is_raw_tty) fe_temp_reset();
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
466static 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
474static 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*/
575void init_signals()
576{
577  #ifdef SIGSEGV
578  si_set_signal(SIGSEGV,(si_hdl_typ)sigsegv_handler);
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
592  si_set_signal(SIGINT ,(si_hdl_typ)sigint_handler);
593  si_set_signal(SIGCHLD, (si_hdl_typ)sig_chld_hdl);
594  si_set_signal(SIGPIPE, (si_hdl_typ)sig_pipe_hdl);
595  si_set_signal(SIGTERM, (si_hdl_typ)sig_term_hdl);
596}
597
Note: See TracBrowser for help on using the repository browser.