source: git/Singular/cntrlc.cc @ b60bfe

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