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

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