source: git/Singular/cntrlc.cc @ 5476e83

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