source: git/Singular/cntrlc.cc @ 9803fb

spielwiese
Last change on this file since 9803fb was 9803fb, checked in by Hans Schoenemann <hannes@…>, 13 years ago
crash handling in childs git-svn-id: file:///usr/local/Singular/svn/trunk@13942 2c84dea3-7e68-4137-9b89-c4e89433aadc
  • Property mode set to 100644
File size: 14.9 KB
RevLine 
[0e1846]1/****************************************
2*  Computer Algebra System SINGULAR     *
3****************************************/
[341696]4/* $Id$ */
[0e1846]5/*
6* ABSTRACT - interupt handling
7*/
8
9/* includes */
[502ea2]10#ifdef DecAlpha_OSF1
11#define _XOPEN_SOURCE_EXTENDED
[d5bd816]12#endif /* MP3-Y2 0.022UF */
[0e1846]13#include <stdio.h>
14#include <stddef.h>
15#include <stdlib.h>
[502ea2]16#include <strings.h>
[0e1846]17#include <signal.h>
[561aa2]18#include <sys/types.h>
19#include <sys/wait.h>
[b1dfaf]20#include <kernel/mod2.h>
21#include <omalloc/omalloc.h>
[599326]22#include <Singular/tok.h>
23#include <Singular/ipshell.h>
24#include <kernel/febase.h>
25#include <Singular/cntrlc.h>
26#include <kernel/polys.h>
27#include <Singular/feOpt.h>
28#include <Singular/version.h>
[ffc237]29#include <Singular/silink.h>
[dc0898]30
[d6681d]31/* undef, if you don't want GDB to come up on error */
[b39d4d]32
33#if !defined(__alpha)
34#define CALL_GDB
35#endif
[d6681d]36
37#if defined(__OPTIMIZE__) && defined(CALL_GDB)
38#undef CALL_GDB
39#endif
40
[337d5b]41#if defined(unix) && !defined(hpux)
42 #include <unistd.h>
43 #include <sys/types.h>
44
45 #ifdef TIME_WITH_SYS_TIME
46   #include <time.h>
47   #ifdef HAVE_SYS_TIME_H
48     #include <sys/time.h>
49   #endif
50 #else
51   #ifdef HAVE_SYS_TIME_H
52     #include <sys/time.h>
53   #else
54     #include <time.h>
55   #endif
56 #endif
57 #ifdef HAVE_SYS_TIMES_H
58   #include <sys/times.h>
59 #endif
60
61 #define INTERACTIVE 0
62 #define STACK_TRACE 1
63
64 #ifdef CALL_GDB
65   static void debug (int);
[a5da6f]66   static void debug_stop (char *const*args);
[337d5b]67 #endif
68 #ifndef __OPTIMIZE__
69   static void stack_trace_sigchld (int);
[a5da6f]70   static void stack_trace (char *const*args);
[337d5b]71 #endif
72#endif
[0e1846]73
[85ab8cd]74si_link pipeLastLink=NULL;
[655e1f]75BOOLEAN singular_in_batchmode=FALSE;
[85ab8cd]76
77void sig_pipe_hdl(int sig)
78{
79 if (pipeLastLink!=NULL)
80 {
81   slClose(pipeLastLink);
82   pipeLastLink=NULL;
83   WerrorS("pipe failed");
84 }
85}
86
[d5bd816]87/*---------------------------------------------------------------------*
88 * File scope Variables (Variables share by several functions in
89 *                       the same file )
90 *
91 *---------------------------------------------------------------------*/
[0e1846]92/* data */
[07dacd]93jmp_buf si_start_jmpbuf;
[0e1846]94int siRandomStart;
[07dacd]95short si_restart=0;
96BOOLEAN siCntrlc = FALSE;
[0e1846]97
[5812c69]98typedef void (*si_hdl_typ)(int);
99
[7c96c03]100
[0e1846]101/*0 implementation*/
[d5bd816]102/*---------------------------------------------------------------------*
103 * Functions declarations
104 *
105 *---------------------------------------------------------------------*/
[0e1846]106void sigint_handler(int sig);
[d5bd816]107
[7c96c03]108si_hdl_typ si_set_signal ( int sig, si_hdl_typ signal_handler);
[d5bd816]109
110/*---------------------------------------------------------------------*/
[337d5b]111/**
[d5bd816]112 * @brief meta function for binding a signal to an handler
113
114 @param[in] sig             Signal number
115 @param[in] signal_handler  Pointer to signal handler
116
117 @return value of signal()
118**/
119/*---------------------------------------------------------------------*/
[85ab8cd]120si_hdl_typ si_set_signal ( int sig, si_hdl_typ signal_handler)
[d5bd816]121{
[7c96c03]122  si_hdl_typ retval=signal (sig, (si_hdl_typ)signal_handler);
123  if (retval == SIG_ERR)
124  {
[d5bd816]125     fprintf(stderr, "Unable to init signal %d ... exiting...\n", sig);
126  }
[206aed]127#ifdef HAVE_SIGINTERRUPT
[d5bd816]128  siginterrupt(sig, 1);
[206aed]129#endif
[d5bd816]130  return retval;
[7c96c03]131}                               /* si_set_signal */
[d5bd816]132
[0e1846]133
[d5bd816]134/*---------------------------------------------------------------------*/
[337d5b]135#if defined(ix86_Linux)
[4f818c]136  #if !defined(HAVE_SIGCONTEXT) && !defined(HAVE_ASM_SIGCONTEXT_H)
[c7a653]137// we need the following structure sigcontext_struct.
138// if configure finds asm/singcontext.h we assume
139// that this file contains the structure and is included
140// via signal.h
[0e1846]141struct sigcontext_struct {
142        unsigned short gs, __gsh;
143        unsigned short fs, __fsh;
144        unsigned short es, __esh;
145        unsigned short ds, __dsh;
146        unsigned long edi;
147        unsigned long esi;
148        unsigned long ebp;
149        unsigned long esp;
150        unsigned long ebx;
151        unsigned long edx;
152        unsigned long ecx;
153        unsigned long eax;
154        unsigned long trapno;
155        unsigned long err;
156        unsigned long eip;
157        unsigned short cs, __csh;
158        unsigned long eflags;
159        unsigned long esp_at_signal;
160        unsigned short ss, __ssh;
161        unsigned long i387;
162        unsigned long oldmask;
163        unsigned long cr2;
164};
[337d5b]165#endif
[f72aa03]166#define HAVE_SIGSTRUCT
[0e1846]167typedef struct sigcontext_struct sigcontext;
[f72aa03]168#endif
[337d5b]169
170#if defined(x86_64_Linux)
[f72aa03]171#define HAVE_SIGSTRUCT
172#endif
[0e1846]173
[d5bd816]174
[337d5b]175#if defined(HAVE_SIGSTRUCT)
[d5bd816]176/*2---------------------------------------------------------------------*/
[337d5b]177/**
178 * @brief signal handler for run time errors, linux/i386, x86_64 version
[d5bd816]179
[337d5b]180 @param[in] sig
181 @param[in] s
[d5bd816]182**/
183/*---------------------------------------------------------------------*/
[0e1846]184void sigsegv_handler(int sig, sigcontext s)
185{
[d7e6e0]186  fprintf(stderr,"Singular : signal %d (v: %d/%s):\n",sig,SINGULAR_VERSION,feVersionId);
[0e1846]187  if (sig!=SIGINT)
188  {
[f9d901]189    fprintf(stderr,"current line:>>%s<<\n",my_yylinebuf);
[1270db]190    fprintf(stderr,"Segment fault/Bus error occurred at %lx because of %lx (r:%d)\n"
[0e1846]191                   "please inform the authors\n",
[c7a653]192                   #ifdef __i386__
[28fc7b]193                   (long)s.eip,
[c7a653]194                   #else /* x86_64*/
[28fc7b]195                   (long)s.rip,
[c7a653]196                   #endif
197                   (long)s.cr2,siRandomStart);
[0e1846]198  }
[337d5b]199#ifdef __OPTIMIZE__
[07dacd]200  if(si_restart<3)
201  {
202    si_restart++;
203    fprintf(stderr,"trying to restart...\n");
204    init_signals();
205    longjmp(si_start_jmpbuf,1);
206  }
[337d5b]207#endif /* __OPTIMIZE__ */
208#ifdef CALL_GDB
[9803fb]209  if (sig!=SIGINT) 
210  {
211    if (singular_in_batchmode) debug(STACK_TRACE);
212    else                       debug(INTERACTIVE);
213  }
[337d5b]214#endif /* CALL_GDB */
[0e1846]215  exit(0);
216}
217
[d5bd816]218/*---------------------------------------------------------------------*/
[337d5b]219/**
[d5bd816]220 * @brief additional default signal handler
221
[6b02bf2]222  // some newer Linux version cannot have SIG_IGN for SIGCHLD,
223  // so use this nice routine here:
224  //  SuSe 9.x reports -1 always
225  //  Redhat 9.x/FC x reports sometimes -1
226  // see also: hpux_system
[951dacc]227  // also needed by getrusage (timer etc.)
[d5bd816]228
[337d5b]229 @param[in] sig
[d5bd816]230**/
231/*---------------------------------------------------------------------*/
232void sig_ign_hdl(int sig)
233{
[561aa2]234 waitpid(-1,NULL,WNOHANG); 
[6b02bf2]235}
236
[0e1846]237/*2
[97eb91]238* init signal handlers, linux/i386 version
[0e1846]239*/
240void init_signals()
241{
242/*4 signal handler: linux*/
[7c96c03]243  if (SIG_ERR==si_set_signal(SIGSEGV,(si_hdl_typ)sigsegv_handler))
[057e93c]244  {
245    PrintS("cannot set signal handler for SEGV\n");
246  }
[7c96c03]247  if (SIG_ERR==si_set_signal(SIGFPE, (si_hdl_typ)sigsegv_handler))
[057e93c]248  {
249    PrintS("cannot set signal handler for FPE\n");
250  }
[7c96c03]251  if (SIG_ERR==si_set_signal(SIGILL, (si_hdl_typ)sigsegv_handler))
[057e93c]252  {
253    PrintS("cannot set signal handler for ILL\n");
254  }
[7c96c03]255  if (SIG_ERR==si_set_signal(SIGIOT, (si_hdl_typ)sigsegv_handler))
[057e93c]256  {
257    PrintS("cannot set signal handler for IOT\n");
258  }
[7c96c03]259  if (SIG_ERR==si_set_signal(SIGINT ,(si_hdl_typ)sigint_handler))
[057e93c]260  {
261    PrintS("cannot set signal handler for INT\n");
262  }
[7c96c03]263  si_set_signal(SIGCHLD, (si_hdl_typ)sig_ign_hdl);
[ffc237]264  si_set_signal(SIGPIPE, (si_hdl_typ)sig_pipe_hdl);
[0e1846]265}
266
[d5bd816]267/*---------------------------------------------------------------------*/
[337d5b]268#elif defined(SunOS) /*SPARC_SUNOS*/
[0e1846]269/*2
270* signal handler for run time errors, sparc sunos 4 version
271*/
272void sigsegv_handler(int sig, int code, struct sigcontext *scp, char *addr)
273{
[d7e6e0]274  fprintf(stderr,"Singular : signal %d, code %d (v: %d/%s):\n",
[c06a32]275    sig,code,SINGULAR_VERSION,feVersionId);
[0e1846]276  if ((sig!=SIGINT)&&(sig!=SIGABRT))
277  {
[f9d901]278    fprintf(stderr,"current line:>>%s<<\n",my_yylinebuf);
[0e1846]279    fprintf(stderr,"Segment fault/Bus error occurred at %x (r:%d)\n"
280                   "please inform the authors\n",
281                   (int)addr,siRandomStart);
282  }
[337d5b]283#ifdef __OPTIMIZE__
[97eb91]284  if(si_restart<3)
285  {
286    si_restart++;
287    fprintf(stderr,"trying to restart...\n");
288    init_signals();
289    longjmp(si_start_jmpbuf,1);
290  }
[337d5b]291#endif /* __OPTIMIZE__ */
292#ifdef CALL_GDB
[0e1846]293  if (sig!=SIGINT) debug(STACK_TRACE);
[337d5b]294#endif /* CALL_GDB */
[0e1846]295  exit(0);
296}
297
298/*2
299* init signal handlers, sparc sunos 4 version
300*/
301void init_signals()
302{
303/*4 signal handler:*/
[7c96c03]304  si_set_signal(SIGSEGV,sigsegv_handler);
305  si_set_signal(SIGBUS, sigsegv_handler);
306  si_set_signal(SIGFPE, sigsegv_handler);
307  si_set_signal(SIGILL, sigsegv_handler);
308  si_set_signal(SIGIOT, sigsegv_handler);
309  si_set_signal(SIGINT ,sigint_handler);
310  si_set_signal(SIGCHLD, (void (*)(int))SIG_IGN);
[85ab8cd]311  si_set_signal(SIGPIPE, (si_hdl_typ)sig_pipe_hdl);
[0e1846]312}
[337d5b]313#else
[0e1846]314
[d5bd816]315/*---------------------------------------------------------------------*/
[0e1846]316/*2
317* signal handler for run time errors, general version
318*/
319void sigsegv_handler(int sig)
320{
[d7e6e0]321  fprintf(stderr,"Singular : signal %d (v: %d/%s):\n",
[c06a32]322    sig,SINGULAR_VERSION,feVersionId);
[0e1846]323  if (sig!=SIGINT)
324  {
[f9d901]325    fprintf(stderr,"current line:>>%s<<\n",my_yylinebuf);
[0e1846]326    fprintf(stderr,"Segment fault/Bus error occurred (r:%d)\n"
327                   "please inform the authors\n",
328                   siRandomStart);
329  }
[337d5b]330  #ifdef __OPTIMIZE__
[97eb91]331  if(si_restart<3)
332  {
333    si_restart++;
334    fprintf(stderr,"trying to restart...\n");
335    init_signals();
336    longjmp(si_start_jmpbuf,1);
337  }
[337d5b]338  #endif /* __OPTIMIZE__ */
339  #if defined(unix) && !defined(hpux)
340  /* debug(..) does not work under HPUX (because ptrace does not work..) */
341  #ifdef CALL_GDB
[0e1846]342  if (sig!=SIGINT) debug(STACK_TRACE);
[337d5b]343  #endif /* CALL_GDB */
344  #endif /* unix */
[0e1846]345  exit(0);
346}
347
348/*2
349* init signal handlers, general version
350*/
351void init_signals()
352{
353/*4 signal handler:*/
[7c96c03]354  si_set_signal(SIGSEGV,(void (*) (int))sigsegv_handler);
[337d5b]355  #ifdef SIGBUS
[7c96c03]356  si_set_signal(SIGBUS, sigsegv_handler);
[337d5b]357  #endif /* SIGBUS */
358  #ifdef SIGFPE
[7c96c03]359  si_set_signal(SIGFPE, sigsegv_handler);
[337d5b]360  #endif /* SIGFPE */
361  #ifdef SIGILL
[7c96c03]362  si_set_signal(SIGILL, sigsegv_handler);
[337d5b]363  #endif /* SIGILL */
364  #ifdef SIGIOT
[7c96c03]365  si_set_signal(SIGIOT, sigsegv_handler);
[337d5b]366  #endif /* SIGIOT */
367  #ifdef SIGXCPU
[7c96c03]368  si_set_signal(SIGXCPU, (void (*)(int))SIG_IGN);
[337d5b]369  #endif /* SIGIOT */
[7c96c03]370  si_set_signal(SIGINT ,sigint_handler);
[337d5b]371  #if defined(HPUX_9) || defined(HPUX_10)
[7c96c03]372  si_set_signal(SIGCHLD, (void (*)(int))SIG_IGN);
[337d5b]373  #endif
[85ab8cd]374  si_set_signal(SIGPIPE, (si_hdl_typ)sig_pipe_hdl);
[0e1846]375}
[337d5b]376#endif
[d5bd816]377
[0e1846]378
379/*2
380* signal handler for SIGINT
381*/
382void sigint_handler(int sig)
383{
[66415e1]384  mflush();
[337d5b]385  #ifdef HAVE_FEREAD
[0fa9018]386  if (fe_is_raw_tty) fe_temp_reset();
[337d5b]387  #endif /* HAVE_FEREAD */
[66415e1]388  loop
389  {
[e8a30d]390    int cnt=0;
[2272c33]391    int c;
[eed07e8]392    if(singular_in_batchmode)
[2272c33]393    {
[eed07e8]394      c = 'q';
[2272c33]395    }
396    else
397    {
[eed07e8]398      fprintf(stderr,"// ** Interrupt at cmd:`%s` in line:'%s'\n",
399        Tok2Cmdname(iiOp),my_yylinebuf);
400      if (feGetOptValue(FE_OPT_EMACS) == NULL)
401      {
402        fputs("abort command(a), continue(c) or quit Singular(q) ?",stderr);fflush(stderr);
403        c = fgetc(stdin);
404      }
405      else
406      {
407        c = 'a';
408      }
[2272c33]409    }
[337d5b]410
[2272c33]411    switch(c)
[66415e1]412    {
413      case 'q':
414                m2_end(2);
[07dacd]415      case 'r':
416                longjmp(si_start_jmpbuf,1);
[09e228]417      case 'b':
418                VoiceBackTrack();
419                break;
[e8a30d]420      case 'a':
421                siCntrlc++;
[66415e1]422      case 'c':
[2272c33]423                if (feGetOptValue(FE_OPT_EMACS) == NULL) fgetc(stdin);
[7c96c03]424                si_set_signal(SIGINT ,(si_hdl_typ)sigint_handler);
[07dacd]425                return;
[50b2df]426                //siCntrlc ++;
[7c96c03]427                //if (siCntrlc>2) si_set_signal(SIGINT,(si_hdl_typ) sigsegv_handler);
428                //else            si_set_signal(SIGINT,(si_hdl_typ) sigint_handler);
[66415e1]429    }
[e8a30d]430    cnt++;
431    if(cnt>5) m2_end(2);
[66415e1]432  }
[0e1846]433}
434
[e8a30d]435//void test_int()
436//{
437//  if (siCntrlc!=0)
438//  {
439//    int saveecho = si_echo;
440//    siCntrlc = FALSE;
[7c96c03]441//    si_set_signal(SIGINT ,sigint_handler);
[e8a30d]442//    iiDebug();
443//    si_echo = saveecho;
444//  }
445//}
[0e1846]446
447#ifdef unix
[d5bd816]448# ifndef hpux
449#  ifndef __OPTIMIZE__
[0e1846]450int si_stop_stack_trace_x;
[d5bd816]451#    ifdef CALL_GDB
[577d19f]452static void debug (int method)
[0e1846]453{
[8a6c6a]454  if (feOptValue(FE_OPT_NO_TTY))
455  {
456    dReportError("Caught Signal 11");
457    return;
458  }
[0e1846]459  int pid;
460  char buf[16];
[a5da6f]461  char * args[4] = { (char*)"gdb", (char*)"Singularg", NULL, NULL };
[577d19f]462
[337d5b]463  #ifdef HAVE_FEREAD
[0fa9018]464  if (fe_is_raw_tty) fe_temp_reset();
[337d5b]465  #endif /* HAVE_FEREAD */
[0fa9018]466
[0e1846]467  sprintf (buf, "%d", getpid ());
468
469  args[2] = buf;
470
471  pid = fork ();
472  if (pid == 0)
473  {
474    switch (method)
475    {
476      case INTERACTIVE:
477        fprintf (stderr, "debug_stop\n");
478        debug_stop (args);
479        break;
[85e68dd]480      #ifndef __OPTIMIZE__
[0e1846]481      case STACK_TRACE:
482        fprintf (stderr, "stack_trace\n");
483        stack_trace (args);
484        break;
[85e68dd]485      #endif
[5687c9]486      default:
487        // should not be reached:
488        exit(1);
[0e1846]489    }
490  }
491  else if (pid == -1)
492  {
493    perror ("could not fork");
494    return;
495  }
496
497  si_stop_stack_trace_x = 1;
498  while (si_stop_stack_trace_x) ;
499}
500
[a5da6f]501static void debug_stop (char *const*args)
[0e1846]502{
503  execvp (args[0], args);
504  perror ("exec failed");
505  _exit (0);
506}
[d5bd816]507#    endif /* CALL_GDB */
[0e1846]508
509static int stack_trace_done;
510
[a5da6f]511static void stack_trace (char *const*args)
[0e1846]512{
513  int pid;
514  int in_fd[2];
515  int out_fd[2];
516  fd_set fdset;
517  fd_set readset;
518  struct timeval tv;
519  int sel, index, state;
520  char buffer[256];
521  char c;
522
523  stack_trace_done = 0;
524
525  signal (SIGCHLD, stack_trace_sigchld);
526
527  if ((pipe (in_fd) == -1) || (pipe (out_fd) == -1))
528  {
529    perror ("could open pipe");
[0fa9018]530    m2_end(999);
[0e1846]531  }
532
533  pid = fork ();
534  if (pid == 0)
535  {
536    close (0); dup2 (in_fd[0],0);   /* set the stdin to the in pipe */
537    close (1); dup2 (out_fd[1],1);  /* set the stdout to the out pipe */
538    close (2); dup2 (out_fd[1],2);  /* set the stderr to the out pipe */
539
540    execvp (args[0], args);      /* exec gdb */
541    perror ("exec failed");
[0fa9018]542    m2_end(999);
[0e1846]543  }
544  else if (pid == -1)
545  {
546    perror ("could not fork");
[0fa9018]547    m2_end(999);
[0e1846]548  }
549
550  FD_ZERO (&fdset);
551  FD_SET (out_fd[0], &fdset);
552
553  write (in_fd[1], "backtrace\n", 10);
554  write (in_fd[1], "p si_stop_stack_trace_x = 0\n", 28);
555  write (in_fd[1], "quit\n", 5);
556
557  index = 0;
558  state = 0;
559
560  loop
561  {
562    readset = fdset;
563    tv.tv_sec = 1;
564    tv.tv_usec = 0;
565
[d5bd816]566#    ifdef hpux
[0e1846]567    sel = select (FD_SETSIZE, (int *)readset.fds_bits, NULL, NULL, &tv);
[d5bd816]568#    else /* hpux */
[0e1846]569    sel = select (FD_SETSIZE, &readset, NULL, NULL, &tv);
[d5bd816]570#    endif /* hpux */
[0e1846]571    if (sel == -1)
572      break;
573
574    if ((sel > 0) && (FD_ISSET (out_fd[0], &readset)))
575    {
576      if (read (out_fd[0], &c, 1))
577      {
578        switch (state)
579        {
580          case 0:
581            if (c == '#')
582            {
583              state = 1;
584              index = 0;
585              buffer[index++] = c;
586            }
587            break;
588          case 1:
589            buffer[index++] = c;
590            if ((c == '\n') || (c == '\r'))
591            {
592              buffer[index] = 0;
593              fprintf (stderr, "%s", buffer);
594              state = 0;
595              index = 0;
596            }
597            break;
598          default:
599            break;
600        }
601      }
602    }
603    else if (stack_trace_done)
604      break;
605  }
606
607  close (in_fd[0]);
608  close (in_fd[1]);
609  close (out_fd[0]);
610  close (out_fd[1]);
[0fa9018]611  m2_end(0);
[0e1846]612}
613
614static void stack_trace_sigchld (int signum)
615{
616  stack_trace_done = 1;
617}
618
[d5bd816]619#  endif /* !__OPTIMIZE__ */
620# endif /* !hpux */
621#endif /* unix */
[dc0898]622
623/* Under HPUX 9, system(...) returns -1 if SIGCHLD does not equal
624   SIG_DFL. However, if it stays at SIG_DFL we get zombie processes
[337d5b]625   for terminated childs generated by fork. Therefors some special treatment
[dc0898]626   is necessary */
627#ifdef HPUX_9
[d5bd816]628# undef system
[dc0898]629extern "C" {
630  int  hpux9_system(const char* call)
631  {
632    int ret;
[7c96c03]633    si_set_signal(SIGCHLD, (void (*)(int))SIG_DFL);
[dc0898]634    ret = system(call);
[7c96c03]635    si_set_signal(SIGCHLD, (void (*)(int))SIG_IGN);
[dc0898]636    return ret;
637  }
638}
639#endif /* HPUX_9 */
Note: See TracBrowser for help on using the repository browser.