source: git/Singular/cntrlc.cc @ bb9471

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