source: git/Singular/cntrlc.cc @ 2fa80a

spielwiese
Last change on this file since 2fa80a was 659a7a, checked in by Andreas Steenpass <steenpass@…>, 10 years ago
chg: defer shutdown caused by SIGTERM if necessary (cherry picked from commit a76a64e703bae29ffee8057ab2b16abb20f9158a) Signed-off-by: Andreas Steenpass <steenpass@mathematik.uni-kl.de> Conflicts: Singular/cntrlc.cc Singular/cntrlc.h Singular/misc_ip.cc
  • Property mode set to 100644
File size: 14.0 KB
RevLine 
[0e1846]1/****************************************
2*  Computer Algebra System SINGULAR     *
3****************************************/
4/*
5* ABSTRACT - interupt handling
6*/
7
8/* includes */
[502ea2]9#ifdef DecAlpha_OSF1
10#define _XOPEN_SOURCE_EXTENDED
[d5bd816]11#endif /* MP3-Y2 0.022UF */
[0e1846]12#include <stdio.h>
13#include <stddef.h>
14#include <stdlib.h>
[502ea2]15#include <strings.h>
[0e1846]16#include <signal.h>
[561aa2]17#include <sys/types.h>
18#include <sys/wait.h>
[ef6f95]19
[16f511]20#ifdef HAVE_CONFIG_H
[ba5e9e]21#include "singularconfig.h"
[16f511]22#endif /* HAVE_CONFIG_H */
[b60bfe]23
[b1dfaf]24#include <kernel/mod2.h>
25#include <omalloc/omalloc.h>
[b60bfe]26#include <Singular/tok.h>
27#include <Singular/ipshell.h>
[599326]28#include <kernel/febase.h>
[751785e]29void sig_chld_hdl(int sig); /*#include <Singular/links/ssiLink.h>*/
[b60bfe]30#include <Singular/cntrlc.h>
31#include <Singular/feOpt.h>
[659a7a]32#include <Singular/misc_ip.h>
[f8565a]33#include <Singular/si_signals.h>
[b60bfe]34#include <Singular/links/silink.h>
35#include <Singular/links/ssiLink.h>
[dc0898]36
[d6681d]37/* undef, if you don't want GDB to come up on error */
[b39d4d]38
[b60bfe]39#define CALL_GDB
40
[d6681d]41#if defined(__OPTIMIZE__) && defined(CALL_GDB)
42#undef CALL_GDB
43#endif
44
[751785e]45#if defined(unix)
[337d5b]46 #include <unistd.h>
47 #include <sys/types.h>
48
49 #ifdef TIME_WITH_SYS_TIME
50   #include <time.h>
51   #ifdef HAVE_SYS_TIME_H
52     #include <sys/time.h>
53   #endif
54 #else
55   #ifdef HAVE_SYS_TIME_H
56     #include <sys/time.h>
57   #else
58     #include <time.h>
59   #endif
60 #endif
61 #ifdef HAVE_SYS_TIMES_H
62   #include <sys/times.h>
63 #endif
64
65 #define INTERACTIVE 0
66 #define STACK_TRACE 1
67
68 #ifdef CALL_GDB
69   static void debug (int);
[a5da6f]70   static void debug_stop (char *const*args);
[337d5b]71 #endif
72 #ifndef __OPTIMIZE__
73   static void stack_trace_sigchld (int);
[a5da6f]74   static void stack_trace (char *const*args);
[337d5b]75 #endif
76#endif
[0e1846]77
[85ab8cd]78si_link pipeLastLink=NULL;
[655e1f]79BOOLEAN singular_in_batchmode=FALSE;
[85ab8cd]80
[2e4ec14]81void sig_pipe_hdl(int /*sig*/)
[85ab8cd]82{
83 if (pipeLastLink!=NULL)
84 {
85   slClose(pipeLastLink);
86   pipeLastLink=NULL;
87   WerrorS("pipe failed");
88 }
89}
90
[659a7a]91volatile BOOLEAN do_shutdown = FALSE;
92volatile int defer_shutdown = 0;
93
[2e4ec14]94void sig_term_hdl(int /*sig*/)
[7626c5f]95{
[659a7a]96  do_shutdown = TRUE;
97  if (!defer_shutdown)
[b60bfe]98  {
[659a7a]99    m2_end(1);
[b60bfe]100  }
[7626c5f]101}
102
[d5bd816]103/*---------------------------------------------------------------------*
104 * File scope Variables (Variables share by several functions in
105 *                       the same file )
106 *
107 *---------------------------------------------------------------------*/
[0e1846]108/* data */
[07dacd]109jmp_buf si_start_jmpbuf;
[0e1846]110int siRandomStart;
[07dacd]111short si_restart=0;
112BOOLEAN siCntrlc = FALSE;
[0e1846]113
[5812c69]114typedef void (*si_hdl_typ)(int);
115
[7c96c03]116
[0e1846]117/*0 implementation*/
[d5bd816]118/*---------------------------------------------------------------------*
119 * Functions declarations
120 *
121 *---------------------------------------------------------------------*/
[b60bfe]122void sigint_handler(int /*sig*/);
[d5bd816]123
[7c96c03]124si_hdl_typ si_set_signal ( int sig, si_hdl_typ signal_handler);
[d5bd816]125
126/*---------------------------------------------------------------------*/
[337d5b]127/**
[d5bd816]128 * @brief meta function for binding a signal to an handler
129
130 @param[in] sig             Signal number
131 @param[in] signal_handler  Pointer to signal handler
132
133 @return value of signal()
134**/
135/*---------------------------------------------------------------------*/
[85ab8cd]136si_hdl_typ si_set_signal ( int sig, si_hdl_typ signal_handler)
[d5bd816]137{
[72de5f]138#if 0
[7c96c03]139  si_hdl_typ retval=signal (sig, (si_hdl_typ)signal_handler);
140  if (retval == SIG_ERR)
141  {
[d5bd816]142     fprintf(stderr, "Unable to init signal %d ... exiting...\n", sig);
143  }
[bdda8c2]144  si_siginterrupt(sig, 0);
[72de5f]145  /*system calls will be restarted if interrupted by  the  specified
146   * signal sig.  This is the default behavior in Linux.
147   */
148#else
149  struct sigaction new_action,old_action;
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
[bdda8c2]158  int r=si_sigaction (sig, &new_action, &old_action);
[72de5f]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  }
[206aed]165#endif
[d5bd816]166  return retval;
[7c96c03]167}                               /* si_set_signal */
[d5bd816]168
[0e1846]169
[d5bd816]170/*---------------------------------------------------------------------*/
[319eab]171#if defined(__linux__) && defined(__i386)
[4f818c]172  #if !defined(HAVE_SIGCONTEXT) && !defined(HAVE_ASM_SIGCONTEXT_H)
[c7a653]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
[0e1846]177struct 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};
[337d5b]201#endif
[f72aa03]202#define HAVE_SIGSTRUCT
[0e1846]203typedef struct sigcontext_struct sigcontext;
[f72aa03]204#endif
[337d5b]205
[319eab]206#if defined(__linux__) && defined(__amd64)
[f72aa03]207#define HAVE_SIGSTRUCT
208#endif
[0e1846]209
[d5bd816]210
[337d5b]211#if defined(HAVE_SIGSTRUCT)
[d5bd816]212/*2---------------------------------------------------------------------*/
[337d5b]213/**
214 * @brief signal handler for run time errors, linux/i386, x86_64 version
[d5bd816]215
[337d5b]216 @param[in] sig
217 @param[in] s
[d5bd816]218**/
219/*---------------------------------------------------------------------*/
[0e1846]220void sigsegv_handler(int sig, sigcontext s)
221{
[92644b]222  fprintf(stderr,"Singular : signal %d (v: %d):\n",sig,SINGULAR_VERSION);
[0e1846]223  if (sig!=SIGINT)
224  {
[f9d901]225    fprintf(stderr,"current line:>>%s<<\n",my_yylinebuf);
[1270db]226    fprintf(stderr,"Segment fault/Bus error occurred at %lx because of %lx (r:%d)\n"
[0e1846]227                   "please inform the authors\n",
[c7a653]228                   #ifdef __i386__
[28fc7b]229                   (long)s.eip,
[c7a653]230                   #else /* x86_64*/
[28fc7b]231                   (long)s.rip,
[c7a653]232                   #endif
233                   (long)s.cr2,siRandomStart);
[0e1846]234  }
[337d5b]235#ifdef __OPTIMIZE__
[07dacd]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  }
[337d5b]243#endif /* __OPTIMIZE__ */
244#ifdef CALL_GDB
[788fdf]245  if (sig!=SIGINT)
[9803fb]246  {
247    if (singular_in_batchmode) debug(STACK_TRACE);
248    else                       debug(INTERACTIVE);
249  }
[337d5b]250#endif /* CALL_GDB */
[0e1846]251  exit(0);
252}
253
[d5bd816]254/*---------------------------------------------------------------------*/
[337d5b]255#elif defined(SunOS) /*SPARC_SUNOS*/
[0e1846]256/*2
257* signal handler for run time errors, sparc sunos 4 version
258*/
259void sigsegv_handler(int sig, int code, struct sigcontext *scp, char *addr)
260{
[92644b]261  fprintf(stderr,"Singular : signal %d, code %d (v: %d):\n",
262    sig,code,SINGULAR_VERSION);
[0e1846]263  if ((sig!=SIGINT)&&(sig!=SIGABRT))
264  {
[f9d901]265    fprintf(stderr,"current line:>>%s<<\n",my_yylinebuf);
[0e1846]266    fprintf(stderr,"Segment fault/Bus error occurred at %x (r:%d)\n"
267                   "please inform the authors\n",
268                   (int)addr,siRandomStart);
269  }
[337d5b]270#ifdef __OPTIMIZE__
[97eb91]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  }
[337d5b]278#endif /* __OPTIMIZE__ */
279#ifdef CALL_GDB
[0e1846]280  if (sig!=SIGINT) debug(STACK_TRACE);
[337d5b]281#endif /* CALL_GDB */
[0e1846]282  exit(0);
283}
[b60bfe]284
[337d5b]285#else
[0e1846]286
[d5bd816]287/*---------------------------------------------------------------------*/
[0e1846]288/*2
289* signal handler for run time errors, general version
290*/
291void sigsegv_handler(int sig)
292{
[92644b]293  fprintf(stderr,"Singular : signal %d (v: %d):\n",
294    sig,SINGULAR_VERSION);
[0e1846]295  if (sig!=SIGINT)
296  {
[f9d901]297    fprintf(stderr,"current line:>>%s<<\n",my_yylinebuf);
[0e1846]298    fprintf(stderr,"Segment fault/Bus error occurred (r:%d)\n"
299                   "please inform the authors\n",
300                   siRandomStart);
301  }
[337d5b]302  #ifdef __OPTIMIZE__
[97eb91]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  }
[337d5b]310  #endif /* __OPTIMIZE__ */
[751785e]311  #if defined(unix)
[337d5b]312  #ifdef CALL_GDB
[0e1846]313  if (sig!=SIGINT) debug(STACK_TRACE);
[337d5b]314  #endif /* CALL_GDB */
315  #endif /* unix */
[0e1846]316  exit(0);
317}
[337d5b]318#endif
[d5bd816]319
[b60bfe]320
[0e1846]321/*2
322* signal handler for SIGINT
323*/
[32cb7a]324int sigint_handler_cnt=0;
[2e4ec14]325void sigint_handler(int /*sig*/)
[0e1846]326{
[66415e1]327  mflush();
[337d5b]328  #ifdef HAVE_FEREAD
[0fa9018]329  if (fe_is_raw_tty) fe_temp_reset();
[337d5b]330  #endif /* HAVE_FEREAD */
[32cb7a]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]; }
[66415e1]335  loop
336  {
[e8a30d]337    int cnt=0;
[2272c33]338    int c;
[32cb7a]339
340    if (singular_in_batchmode)
[2272c33]341    {
[eed07e8]342      c = 'q';
[2272c33]343    }
[32cb7a]344    else if (default_opt!=' ')
345    {
346      c = default_opt;
347    }
[2272c33]348    else
349    {
[eed07e8]350      fprintf(stderr,"// ** Interrupt at cmd:`%s` in line:'%s'\n",
351        Tok2Cmdname(iiOp),my_yylinebuf);
352      if (feGetOptValue(FE_OPT_EMACS) == NULL)
353      {
[32cb7a]354        fputs("abort after this command(a), abort immediately(r), print backtrace(b), continue(c) or quit Singular(q) ?",stderr);fflush(stderr);
[eed07e8]355        c = fgetc(stdin);
356      }
357      else
358      {
359        c = 'a';
360      }
[2272c33]361    }
[337d5b]362
[2272c33]363    switch(c)
[66415e1]364    {
[32cb7a]365      case 'q': case EOF:
[66415e1]366                m2_end(2);
[07dacd]367      case 'r':
[32cb7a]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;
[09e228]381      case 'b':
382                VoiceBackTrack();
383                break;
[e8a30d]384      case 'a':
385                siCntrlc++;
[66415e1]386      case 'c':
[32cb7a]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                }
[7c96c03]392                si_set_signal(SIGINT ,(si_hdl_typ)sigint_handler);
[07dacd]393                return;
[50b2df]394                //siCntrlc ++;
[7c96c03]395                //if (siCntrlc>2) si_set_signal(SIGINT,(si_hdl_typ) sigsegv_handler);
396                //else            si_set_signal(SIGINT,(si_hdl_typ) sigint_handler);
[66415e1]397    }
[e8a30d]398    cnt++;
399    if(cnt>5) m2_end(2);
[66415e1]400  }
[0e1846]401}
402
[e8a30d]403//void test_int()
404//{
405//  if (siCntrlc!=0)
406//  {
407//    int saveecho = si_echo;
408//    siCntrlc = FALSE;
[7c96c03]409//    si_set_signal(SIGINT ,sigint_handler);
[e8a30d]410//    iiDebug();
411//    si_echo = saveecho;
412//  }
413//}
[0e1846]414
415#ifdef unix
[d5bd816]416#  ifndef __OPTIMIZE__
[ccae2f]417volatile int si_stop_stack_trace_x;
[d5bd816]418#    ifdef CALL_GDB
[577d19f]419static void debug (int method)
[0e1846]420{
[8a6c6a]421  if (feOptValue(FE_OPT_NO_TTY))
422  {
423    dReportError("Caught Signal 11");
424    return;
425  }
[0e1846]426  int pid;
427  char buf[16];
[a5da6f]428  char * args[4] = { (char*)"gdb", (char*)"Singularg", NULL, NULL };
[577d19f]429
[337d5b]430  #ifdef HAVE_FEREAD
[0fa9018]431  if (fe_is_raw_tty) fe_temp_reset();
[337d5b]432  #endif /* HAVE_FEREAD */
[0fa9018]433
[0e1846]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:
[ccae2f]444        fprintf (stderr, "\n\nquit with \"p si_stop_stack_trace_x=0\"\n\n\n");
[0e1846]445        debug_stop (args);
446        break;
447      case STACK_TRACE:
448        fprintf (stderr, "stack_trace\n");
449        stack_trace (args);
450        break;
[5687c9]451      default:
452        // should not be reached:
453        exit(1);
[0e1846]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
[a5da6f]466static void debug_stop (char *const*args)
[0e1846]467{
468  execvp (args[0], args);
469  perror ("exec failed");
470  _exit (0);
471}
[d5bd816]472#    endif /* CALL_GDB */
[0e1846]473
[a5da6f]474static void stack_trace (char *const*args)
[0e1846]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");
[0fa9018]489    m2_end(999);
[0e1846]490  }
491
492  pid = fork ();
493  if (pid == 0)
494  {
[bdda8c2]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 */
[0e1846]498
499    execvp (args[0], args);      /* exec gdb */
500    perror ("exec failed");
[0fa9018]501    m2_end(999);
[0e1846]502  }
503  else if (pid == -1)
504  {
505    perror ("could not fork");
[0fa9018]506    m2_end(999);
[0e1846]507  }
508
509  FD_ZERO (&fdset);
510  FD_SET (out_fd[0], &fdset);
511
[bdda8c2]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);
[0e1846]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
[bdda8c2]525    sel = si_select (FD_SETSIZE, &readset, NULL, NULL, &tv);
[0e1846]526    if (sel == -1)
527      break;
528
529    if ((sel > 0) && (FD_ISSET (out_fd[0], &readset)))
530    {
[bdda8c2]531      if (si_read (out_fd[0], &c, 1))
[0e1846]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    }
[ccae2f]558    else if (si_stop_stack_trace_x==0)
[0e1846]559      break;
560  }
561
[bdda8c2]562  si_close (in_fd[0]);
563  si_close (in_fd[1]);
564  si_close (out_fd[0]);
565  si_close (out_fd[1]);
[0fa9018]566  m2_end(0);
[0e1846]567}
568
[d5bd816]569#  endif /* !__OPTIMIZE__ */
570#endif /* unix */
[dc0898]571
[751785e]572/*2
573* init signal handlers
574*/
575void init_signals()
576{
[60596c]577  #ifdef SIGSEGV
[751785e]578  si_set_signal(SIGSEGV,(si_hdl_typ)sigsegv_handler);
[60596c]579  #endif
580  #ifdef SIGBUS
581  si_set_signal(SIGBUS, (si_hdl_typ)sigsegv_handler);
582  #endif
583  #ifdef SIGFPE
[751785e]584  si_set_signal(SIGFPE, (si_hdl_typ)sigsegv_handler);
[60596c]585  #endif
586  #ifdef SIGILL
[751785e]587  si_set_signal(SIGILL, (si_hdl_typ)sigsegv_handler);
[60596c]588  #endif
589  #ifdef SIGIOT
[751785e]590  si_set_signal(SIGIOT, (si_hdl_typ)sigsegv_handler);
[60596c]591  #endif
[751785e]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);
[dc0898]596}
[751785e]597
Note: See TracBrowser for help on using the repository browser.