source: git/Singular/cntrlc.cc @ 850277

spielwiese
Last change on this file since 850277 was 850277, checked in by Hans Schoenemann <hannes@…>, 10 years ago
chg: moved reading/writing numbers via ssi to coeffs (p.1)
  • 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#include <stdio.h>
13#include <stddef.h>
14#include <stdlib.h>
15#include <strings.h>
16#include <signal.h>
17#include <sys/types.h>
18#include <sys/wait.h>
19
20#ifdef HAVE_CONFIG_H
21#include "singularconfig.h"
22#endif /* HAVE_CONFIG_H */
23
24#include <kernel/mod2.h>
25#include <omalloc/omalloc.h>
26#include <Singular/tok.h>
27#include <Singular/ipshell.h>
28#include <kernel/febase.h>
29void sig_chld_hdl(int sig); /*#include <Singular/links/ssiLink.h>*/
30#include <Singular/cntrlc.h>
31#include <Singular/feOpt.h>
32#include <Singular/misc_ip.h>
33#include <reporter/si_signals.h>
34#include <Singular/links/silink.h>
35#include <Singular/links/ssiLink.h>
36
37/* undef, if you don't want GDB to come up on error */
38
39#define CALL_GDB
40
41#if defined(__OPTIMIZE__) && defined(CALL_GDB)
42#undef CALL_GDB
43#endif
44
45#if defined(unix)
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);
70   static void debug_stop (char *const*args);
71 #endif
72 #ifndef __OPTIMIZE__
73   static void stack_trace_sigchld (int);
74   static void stack_trace (char *const*args);
75 #endif
76#endif
77
78si_link pipeLastLink=NULL;
79BOOLEAN singular_in_batchmode=FALSE;
80
81void sig_pipe_hdl(int /*sig*/)
82{
83 if (pipeLastLink!=NULL)
84 {
85   slClose(pipeLastLink);
86   pipeLastLink=NULL;
87   WerrorS("pipe failed");
88 }
89}
90
91volatile BOOLEAN do_shutdown = FALSE;
92volatile int defer_shutdown = 0;
93
94void sig_term_hdl(int /*sig*/)
95{
96  do_shutdown = TRUE;
97  if (!defer_shutdown)
98  {
99    m2_end(1);
100  }
101}
102
103/*---------------------------------------------------------------------*
104 * File scope Variables (Variables share by several functions in
105 *                       the same file )
106 *
107 *---------------------------------------------------------------------*/
108/* data */
109jmp_buf si_start_jmpbuf;
110int siRandomStart;
111short si_restart=0;
112BOOLEAN siCntrlc = FALSE;
113
114typedef void (*si_hdl_typ)(int);
115
116
117/*0 implementation*/
118/*---------------------------------------------------------------------*
119 * Functions declarations
120 *
121 *---------------------------------------------------------------------*/
122void sigint_handler(int /*sig*/);
123
124si_hdl_typ si_set_signal ( int sig, si_hdl_typ signal_handler);
125
126/*---------------------------------------------------------------------*/
127/**
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/*---------------------------------------------------------------------*/
136si_hdl_typ si_set_signal ( int sig, si_hdl_typ signal_handler)
137{
138#if 0
139  si_hdl_typ retval=signal (sig, (si_hdl_typ)signal_handler);
140  if (retval == SIG_ERR)
141  {
142     fprintf(stderr, "Unable to init signal %d ... exiting...\n", sig);
143  }
144  si_siginterrupt(sig, 0);
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  memset(&new_action, 0, sizeof(struct sigaction));
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(__linux__) && defined(__i386)
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(__linux__) && defined(__amd64)
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):\n",sig,SINGULAR_VERSION);
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):\n",
263    sig,code,SINGULAR_VERSION);
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
286#else
287
288/*---------------------------------------------------------------------*/
289/*2
290* signal handler for run time errors, general version
291*/
292void sigsegv_handler(int sig)
293{
294  fprintf(stderr,"Singular : signal %d (v: %d):\n",
295    sig,SINGULAR_VERSION);
296  if (sig!=SIGINT)
297  {
298    fprintf(stderr,"current line:>>%s<<\n",my_yylinebuf);
299    fprintf(stderr,"Segment fault/Bus error occurred (r:%d)\n"
300                   "please inform the authors\n",
301                   siRandomStart);
302  }
303  #ifdef __OPTIMIZE__
304  if(si_restart<3)
305  {
306    si_restart++;
307    fprintf(stderr,"trying to restart...\n");
308    init_signals();
309    longjmp(si_start_jmpbuf,1);
310  }
311  #endif /* __OPTIMIZE__ */
312  #if defined(unix)
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
322/*2
323* signal handler for SIGINT
324*/
325int sigint_handler_cnt=0;
326void sigint_handler(int /*sig*/)
327{
328  mflush();
329  #ifdef HAVE_FEREAD
330  if (fe_is_raw_tty) fe_temp_reset();
331  #endif /* HAVE_FEREAD */
332  char default_opt=' ';
333  if ((feOptSpec[FE_OPT_CNTRLC].value!=NULL)
334      && ((char*)(feOptSpec[FE_OPT_CNTRLC].value))[0])
335  { default_opt=((char*)(feOptSpec[FE_OPT_CNTRLC].value))[0]; }
336  loop
337  {
338    int cnt=0;
339    int c;
340
341    if (singular_in_batchmode)
342    {
343      c = 'q';
344    }
345    else if (default_opt!=' ')
346    {
347      c = default_opt;
348    }
349    else
350    {
351      fprintf(stderr,"// ** Interrupt at cmd:`%s` in line:'%s'\n",
352        Tok2Cmdname(iiOp),my_yylinebuf);
353      if (feOptValue(FE_OPT_EMACS) == NULL)
354      {
355        fputs("abort after this command(a), abort immediately(r), print backtrace(b), continue(c) or quit Singular(q) ?",stderr);fflush(stderr);
356        c = fgetc(stdin);
357      }
358      else
359      {
360        c = 'a';
361      }
362    }
363
364    switch(c)
365    {
366      case 'q': case EOF:
367                m2_end(2);
368      case 'r':
369                if (sigint_handler_cnt<3)
370                {
371                  sigint_handler_cnt++;
372                  fputs("** Warning: Singular should be restarted as soon as possible **\n",stderr);
373                  fflush(stderr);
374                  longjmp(si_start_jmpbuf,1);
375                }
376                else
377                {
378                  fputs("** tried too often, try another possibility **\n",stderr);
379                  fflush(stderr);
380                }
381                break;
382      case 'b':
383                VoiceBackTrack();
384                break;
385      case 'a':
386                siCntrlc++;
387      case 'c':
388                if ((feOptValue(FE_OPT_EMACS) == NULL) && (default_opt!=' '))
389                {
390                  /* Read until a newline or EOF */
391                  while (c != EOF && c != '\n') c = fgetc(stdin);
392                }
393                si_set_signal(SIGINT ,(si_hdl_typ)sigint_handler);
394                return;
395                //siCntrlc ++;
396                //if (siCntrlc>2) si_set_signal(SIGINT,(si_hdl_typ) sigsegv_handler);
397                //else            si_set_signal(SIGINT,(si_hdl_typ) sigint_handler);
398    }
399    cnt++;
400    if(cnt>5) m2_end(2);
401  }
402}
403
404//void test_int()
405//{
406//  if (siCntrlc!=0)
407//  {
408//    int saveecho = si_echo;
409//    siCntrlc = FALSE;
410//    si_set_signal(SIGINT ,sigint_handler);
411//    iiDebug();
412//    si_echo = saveecho;
413//  }
414//}
415
416#ifdef unix
417#  ifndef __OPTIMIZE__
418volatile int si_stop_stack_trace_x;
419#    ifdef CALL_GDB
420static void debug (int method)
421{
422  if (feOptValue(FE_OPT_NO_TTY))
423  {
424    dReportError("Caught Signal 11");
425    return;
426  }
427  int pid;
428  char buf[16];
429  char * args[4] = { (char*)"gdb", (char*)"Singular", NULL, NULL };
430
431  #ifdef HAVE_FEREAD
432  if (fe_is_raw_tty) fe_temp_reset();
433  #endif /* HAVE_FEREAD */
434
435  sprintf (buf, "%d", getpid ());
436
437  args[2] = buf;
438
439  pid = fork ();
440  if (pid == 0)
441  {
442    switch (method)
443    {
444      case INTERACTIVE:
445        fprintf (stderr, "\n\nquit with \"p si_stop_stack_trace_x=0\"\n\n\n");
446        debug_stop (args);
447        break;
448      case STACK_TRACE:
449        fprintf (stderr, "stack_trace\n");
450        stack_trace (args);
451        break;
452      default:
453        // should not be reached:
454        exit(1);
455    }
456  }
457  else if (pid == -1)
458  {
459    perror ("could not fork");
460    return;
461  }
462
463  si_stop_stack_trace_x = 1;
464  while (si_stop_stack_trace_x) ;
465}
466
467static void debug_stop (char *const*args)
468{
469  execvp (args[0], args);
470  perror ("exec failed");
471  _exit (0);
472}
473#    endif /* CALL_GDB */
474
475static void stack_trace (char *const*args)
476{
477  int pid;
478  int in_fd[2];
479  int out_fd[2];
480  fd_set fdset;
481  fd_set readset;
482  struct timeval tv;
483  int sel, index, state;
484  char buffer[256];
485  char c;
486
487  if ((pipe (in_fd) == -1) || (pipe (out_fd) == -1))
488  {
489    perror ("could open pipe");
490    m2_end(999);
491  }
492
493  pid = fork ();
494  if (pid == 0)
495  {
496    si_close (0); si_dup2 (in_fd[0],0);   /* set the stdin to the in pipe */
497    si_close (1); si_dup2 (out_fd[1],1);  /* set the stdout to the out pipe */
498    si_close (2); si_dup2 (out_fd[1],2);  /* set the stderr to the out pipe */
499
500    execvp (args[0], args);      /* exec gdb */
501    perror ("exec failed");
502    m2_end(999);
503  }
504  else if (pid == -1)
505  {
506    perror ("could not fork");
507    m2_end(999);
508  }
509
510  FD_ZERO (&fdset);
511  FD_SET (out_fd[0], &fdset);
512
513  si_write (in_fd[1], "backtrace\n", 10);
514  si_write (in_fd[1], "p si_stop_stack_trace_x = 0\n", 28);
515  si_write (in_fd[1], "quit\n", 5);
516
517  index = 0;
518  state = 0;
519
520  loop
521  {
522    readset = fdset;
523    tv.tv_sec = 1;
524    tv.tv_usec = 0;
525
526    sel = si_select (FD_SETSIZE, &readset, NULL, NULL, &tv);
527    if (sel == -1)
528      break;
529
530    if ((sel > 0) && (FD_ISSET (out_fd[0], &readset)))
531    {
532      if (si_read (out_fd[0], &c, 1))
533      {
534        switch (state)
535        {
536          case 0:
537            if (c == '#')
538            {
539              state = 1;
540              index = 0;
541              buffer[index++] = c;
542            }
543            break;
544          case 1:
545            buffer[index++] = c;
546            if ((c == '\n') || (c == '\r'))
547            {
548              buffer[index] = 0;
549              fprintf (stderr, "%s", buffer);
550              state = 0;
551              index = 0;
552            }
553            break;
554          default:
555            break;
556        }
557      }
558    }
559    else if (si_stop_stack_trace_x==0)
560      break;
561  }
562
563  si_close (in_fd[0]);
564  si_close (in_fd[1]);
565  si_close (out_fd[0]);
566  si_close (out_fd[1]);
567  m2_end(0);
568}
569
570#  endif /* !__OPTIMIZE__ */
571#endif /* unix */
572
573/*2
574* init signal handlers
575*/
576void init_signals()
577{
578  #ifdef SIGSEGV
579  si_set_signal(SIGSEGV,(si_hdl_typ)sigsegv_handler);
580  #endif
581  #ifdef SIGBUS
582  si_set_signal(SIGBUS, (si_hdl_typ)sigsegv_handler);
583  #endif
584  #ifdef SIGFPE
585  si_set_signal(SIGFPE, (si_hdl_typ)sigsegv_handler);
586  #endif
587  #ifdef SIGILL
588  si_set_signal(SIGILL, (si_hdl_typ)sigsegv_handler);
589  #endif
590  #ifdef SIGIOT
591  si_set_signal(SIGIOT, (si_hdl_typ)sigsegv_handler);
592  #endif
593  si_set_signal(SIGINT ,(si_hdl_typ)sigint_handler);
594  si_set_signal(SIGCHLD, (si_hdl_typ)sig_chld_hdl);
595  si_set_signal(SIGPIPE, (si_hdl_typ)sig_pipe_hdl);
596  si_set_signal(SIGTERM, (si_hdl_typ)sig_term_hdl);
597}
598
Note: See TracBrowser for help on using the repository browser.