source: git/Singular/cntrlc.cc @ f72aa03

spielwiese
Last change on this file since f72aa03 was f72aa03, checked in by Hans Schönemann <hannes@…>, 18 years ago
*hannes: segv handler for x86_64 git-svn-id: file:///usr/local/Singular/svn/trunk@9439 2c84dea3-7e68-4137-9b89-c4e89433aadc
  • Property mode set to 100644
File size: 17.8 KB
Line 
1/****************************************
2*  Computer Algebra System SINGULAR     *
3****************************************/
4/* $Id: cntrlc.cc,v 1.50 2006-10-04 12:37:42 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#ifdef PAGE_TEST
28#include "page.h"
29#endif /* PAGE_TEST */
30
31
32/* undef, if you don't want GDB to come up on error */
33
34#if !defined(__alpha)
35#define CALL_GDB
36#endif
37
38#if defined(__OPTIMIZE__) && defined(CALL_GDB)
39#undef CALL_GDB
40#endif
41
42#ifdef unix
43# ifndef hpux
44#  include <unistd.h>
45#  include <sys/types.h>
46
47#  ifdef TIME_WITH_SYS_TIME
48#   include <time.h>
49#   ifdef HAVE_SYS_TIME_H
50#     include <sys/time.h>
51#   endif
52#  else
53#   ifdef HAVE_SYS_TIME_H
54#     include <sys/time.h>
55#   else
56#     include <time.h>
57#   endif
58#  endif
59#  ifdef HAVE_SYS_TIMES_H
60#   include <sys/times.h>
61#  endif
62
63#  define INTERACTIVE 0
64#  define STACK_TRACE 1
65#  ifdef CALL_GDB
66static void debug (int);
67static void debug_stop (char **);
68#  endif
69#  ifndef __OPTIMIZE__
70static void stack_trace (char **);
71static void stack_trace_sigchld (int);
72#  endif
73# endif /* !hpux */
74#endif  /* unix */
75
76/*---------------------------------------------------------------------*
77 * File scope Variables (Variables share by several functions in
78 *                       the same file )
79 *
80 *---------------------------------------------------------------------*/
81/* data */
82jmp_buf si_start_jmpbuf;
83int siRandomStart;
84short si_restart=0;
85BOOLEAN siCntrlc = FALSE;
86
87typedef void (*si_hdl_typ)(int);
88
89
90/*0 implementation*/
91/*---------------------------------------------------------------------*
92 * Functions declarations
93 *
94 *---------------------------------------------------------------------*/
95#ifndef MSDOS
96/* signals are not implemented in DJGCC */
97void sigint_handler(int sig);
98#endif /* MSDOS */
99
100si_hdl_typ si_set_signal ( int sig, si_hdl_typ signal_handler);
101
102/*---------------------------------------------------------------------*/
103/**
104 * @brief meta function for binding a signal to an handler
105
106 @param[in] sig             Signal number
107 @param[in] signal_handler  Pointer to signal handler
108
109 @return value of signal()
110**/
111/*---------------------------------------------------------------------*/
112si_hdl_typ si_set_signal (
113  int sig,
114  si_hdl_typ signal_handler
115  )
116{
117  si_hdl_typ retval=signal (sig, (si_hdl_typ)signal_handler);
118  if (retval == SIG_ERR)
119  {
120     fprintf(stderr, "Unable to init signal %d ... exiting...\n", sig);
121  }
122#ifdef HAVE_SIGINTERRUPT
123  siginterrupt(sig, 1);
124#endif
125  return retval;
126}                               /* si_set_signal */
127
128
129/*---------------------------------------------------------------------*/
130/*-- linux and i386 ---*/
131#if defined(linux) && defined(__i386__)
132# if defined(HAVE_SIGCONTEXT) || defined(HAVE_ASM_SIGCONTEXT_H)
133#  include <asm/sigcontext.h>
134# else
135struct sigcontext_struct {
136        unsigned short gs, __gsh;
137        unsigned short fs, __fsh;
138        unsigned short es, __esh;
139        unsigned short ds, __dsh;
140        unsigned long edi;
141        unsigned long esi;
142        unsigned long ebp;
143        unsigned long esp;
144        unsigned long ebx;
145        unsigned long edx;
146        unsigned long ecx;
147        unsigned long eax;
148        unsigned long trapno;
149        unsigned long err;
150        unsigned long eip;
151        unsigned short cs, __csh;
152        unsigned long eflags;
153        unsigned long esp_at_signal;
154        unsigned short ss, __ssh;
155        unsigned long i387;
156        unsigned long oldmask;
157        unsigned long cr2;
158};
159#define HAVE_SIGSTRUCT
160# endif
161typedef struct sigcontext_struct sigcontext;
162#endif
163#if defined(linux) && defined(x86_64_Linux)
164struct sigcontext_struct {
165        unsigned long r8;
166        unsigned long r9;
167        unsigned long r10;
168        unsigned long r11;
169        unsigned long r12;
170        unsigned long r13;
171        unsigned long r14;
172        unsigned long r15;
173        unsigned long rdi;
174        unsigned long rsi;
175        unsigned long rbp;
176        unsigned long rbx;
177        unsigned long rdx;
178        unsigned long rax;
179        unsigned long rcx;
180        unsigned long rsp;
181        unsigned long eip /*rip*/;
182        unsigned long eflags;           /* RFLAGS */
183        unsigned short cs;
184        unsigned short gs;
185        unsigned short fs;
186        unsigned short __pad0;
187        unsigned long err;
188        unsigned long trapno;
189        unsigned long oldmask;
190        unsigned long cr2;
191        struct _fpstate __user *fpstate;        /* zero when no FPU context */
192        unsigned long reserved1[8];
193};
194#define HAVE_SIGSTRUCT
195typedef struct sigcontext_struct sigcontext;
196#endif
197
198
199#if defined(linux) && defined(HAVE_SIGSTRUCT)
200/*2---------------------------------------------------------------------*/
201/**
202 * @brief signal handler for run time errors, linux/i386 version
203
204 @param[in] sig     
205 @param[in] s   
206**/
207/*---------------------------------------------------------------------*/
208void sigsegv_handler(int sig, sigcontext s)
209{
210  fprintf(stderr,"Singular : signal %d (v: %d/%u):\n",sig,SINGULAR_VERSION,feVersionId);
211  if (sig!=SIGINT)
212  {
213    fprintf(stderr,"Segment fault/Bus error occurred at %x because of %x (r:%d)\n"
214                   "please inform the authors\n",
215                   (long)s.eip,(long)s.cr2,siRandomStart);
216  }
217# ifdef __OPTIMIZE__
218  if(si_restart<3)
219  {
220    si_restart++;
221    fprintf(stderr,"trying to restart...\n");
222    init_signals();
223    longjmp(si_start_jmpbuf,1);
224  }
225# endif /* __OPTIMIZE__ */
226# ifdef CALL_GDB
227  if (sig!=SIGINT) debug(INTERACTIVE);
228# endif /* CALL_GDB */
229  exit(0);
230}
231
232/*---------------------------------------------------------------------*/
233/**
234 * @brief additional default signal handler
235
236  // some newer Linux version cannot have SIG_IGN for SIGCHLD,
237  // so use this nice routine here:
238  //  SuSe 9.x reports -1 always
239  //  Redhat 9.x/FC x reports sometimes -1
240  // see also: hpux_system
241
242 @param[in] sig     
243**/
244/*---------------------------------------------------------------------*/
245void sig_ign_hdl(int sig)
246{
247}
248
249# ifdef PAGE_TEST
250#  ifndef PAGE_INTERRUPT_TIME
251#   define PAGE_INTERRUPT_TIME 1
252#  endif
253
254/*---------------------------------------------------------------------*/
255/**
256 * @brief signal handler for segmentation faults
257
258 @param[in] sig     
259 @param[in] s   
260**/
261/*---------------------------------------------------------------------*/
262void sig11_handler(int sig, sigcontext s)
263{
264  unsigned long base =(unsigned long)(s.cr2&(~4095));
265  int i;
266  i=mmPage_tab_ind-1;
267  while (mmPage_tab[i]!=base) i--;
268  mmUse_tab[i]='1';
269  mmPage_tab_acc++;
270  mmPage_AllowAccess((void *)base);
271  si_set_signal(SIGSEGV,(si_hdl_typ)sig11_handler);
272}
273
274/*---------------------------------------------------------------------*/
275/**
276 * @brief signal handler for alarm signals
277
278 @param[in] sig     
279 @param[in] s   
280**/
281/*---------------------------------------------------------------------*/
282void sigalarm_handler(int sig, sigcontext s)
283{
284  int i=mmPage_tab_ind-1;
285  mmWriteStat();
286  for(;i>=0;i--)
287  {
288    mmPage_DenyAccess((void *)mmPage_tab[i]);
289  }
290  struct itimerval t,o;
291  memset(&t,0,sizeof(t));
292  t.it_value.tv_sec     =(unsigned)0;
293  t.it_value.tv_usec    =(unsigned) PAGE_INTERRUPT_TIME;
294  o.it_value.tv_sec     =(unsigned)0;
295  o.it_value.tv_usec    =(unsigned)PAGE_INTERRUPT_TIME;
296  setitimer(ITIMER_VIRTUAL,&t,&o);
297  si_set_signal(SIGVTALRM,(si_hdl_typ)sigalarm_handler);
298}
299#endif /* PAGE_TEST */
300
301/*2
302* init signal handlers, linux/i386 version
303*/
304void init_signals()
305{
306/*4 signal handler: linux*/
307# ifdef PAGE_TEST
308  si_set_signal(SIGSEGV,(si_hdl_typ)sig11_handler);
309  struct itimerval t,o;
310  memset(&t,0,sizeof(t));
311  t.it_value.tv_sec     =(unsigned)0;
312  t.it_value.tv_usec    =(unsigned)PAGE_INTERRUPT_TIME;
313  o.it_value.tv_sec     =(unsigned)0;
314  o.it_value.tv_usec    =(unsigned)PAGE_INTERRUPT_TIME;
315  setitimer(ITIMER_VIRTUAL,&t,&o);
316  si_set_signal(SIGVTALRM,(si_hdl_typ)sigalarm_handler);
317# else /* PAGE_TEST */
318  if (SIG_ERR==si_set_signal(SIGSEGV,(si_hdl_typ)sigsegv_handler))
319  {
320    PrintS("cannot set signal handler for SEGV\n");
321  }
322# endif /* PAGE_TEST */
323  if (SIG_ERR==si_set_signal(SIGFPE, (si_hdl_typ)sigsegv_handler))
324  {
325    PrintS("cannot set signal handler for FPE\n");
326  }
327  if (SIG_ERR==si_set_signal(SIGILL, (si_hdl_typ)sigsegv_handler))
328  {
329    PrintS("cannot set signal handler for ILL\n");
330  }
331  if (SIG_ERR==si_set_signal(SIGIOT, (si_hdl_typ)sigsegv_handler))
332  {
333    PrintS("cannot set signal handler for IOT\n");
334  }
335  if (SIG_ERR==si_set_signal(SIGINT ,(si_hdl_typ)sigint_handler))
336  {
337    PrintS("cannot set signal handler for INT\n");
338  }
339  //si_set_signal(SIGCHLD, (void (*)(int))SIG_IGN);
340  si_set_signal(SIGCHLD, (si_hdl_typ)sig_ign_hdl);
341}
342
343#else /* linux && __i386__ */
344/*---------------------------------------------------------------------*/
345/*-- SPARC_SUNOS_4 ---*/
346# ifdef SPARC_SUNOS_4
347/*2
348* signal handler for run time errors, sparc sunos 4 version
349*/
350void sigsegv_handler(int sig, int code, struct sigcontext *scp, char *addr)
351{
352  fprintf(stderr,"Singular : signal %d, code %d (v: %d/%u):\n",
353    sig,code,SINGULAR_VERSION,feVersionId);
354  if ((sig!=SIGINT)&&(sig!=SIGABRT))
355  {
356    fprintf(stderr,"Segment fault/Bus error occurred at %x (r:%d)\n"
357                   "please inform the authors\n",
358                   (int)addr,siRandomStart);
359  }
360#  ifdef __OPTIMIZE__
361  if(si_restart<3)
362  {
363    si_restart++;
364    fprintf(stderr,"trying to restart...\n");
365    init_signals();
366    longjmp(si_start_jmpbuf,1);
367  }
368#  endif /* __OPTIMIZE__ */
369#  ifdef CALL_GDB
370  if (sig!=SIGINT) debug(STACK_TRACE);
371#  endif /* CALL_GDB */
372  exit(0);
373}
374
375/*2
376* init signal handlers, sparc sunos 4 version
377*/
378void init_signals()
379{
380/*4 signal handler:*/
381  si_set_signal(SIGSEGV,sigsegv_handler);
382  si_set_signal(SIGBUS, sigsegv_handler);
383  si_set_signal(SIGFPE, sigsegv_handler);
384  si_set_signal(SIGILL, sigsegv_handler);
385  si_set_signal(SIGIOT, sigsegv_handler);
386  si_set_signal(SIGINT ,sigint_handler);
387  si_set_signal(SIGCHLD, (void (*)(int))SIG_IGN);
388}
389# else /* SPARC_SUNOS_4 */
390
391/*---------------------------------------------------------------------*/
392/*2
393* signal handler for run time errors, general version
394*/
395void sigsegv_handler(int sig)
396{
397  fprintf(stderr,"Singular : signal %d (v: %d/%u):\n",
398    sig,SINGULAR_VERSION,feVersionId);
399  if (sig!=SIGINT)
400  {
401    fprintf(stderr,"Segment fault/Bus error occurred (r:%d)\n"
402                   "please inform the authors\n",
403                   siRandomStart);
404  }
405#   ifdef __OPTIMIZE__
406  if(si_restart<3)
407  {
408    si_restart++;
409    fprintf(stderr,"trying to restart...\n");
410    init_signals();
411    longjmp(si_start_jmpbuf,1);
412  }
413#   endif /* __OPTIMIZE__ */
414#   ifdef unix
415#    ifndef hpux
416/* debug(..) does not work under HPUX (because ptrace does not work..) */
417#     ifdef CALL_GDB
418#      ifndef MSDOS
419  if (sig!=SIGINT) debug(STACK_TRACE);
420#      endif /* MSDOS */
421#     endif /* CALL_GDB */
422#    endif /* !hpux */
423#   endif /* unix */
424  exit(0);
425}
426
427/*2
428* init signal handlers, general version
429*/
430void init_signals()
431{
432#  ifndef MSDOS
433/* signals are not implemented in DJGCC */
434/*4 signal handler:*/
435  si_set_signal(SIGSEGV,(void (*) (int))sigsegv_handler);
436#    ifdef SIGBUS
437  si_set_signal(SIGBUS, sigsegv_handler);
438#    endif /* SIGBUS */
439#    ifdef SIGFPE
440  si_set_signal(SIGFPE, sigsegv_handler);
441#    endif /* SIGFPE */
442#    ifdef SIGILL
443  si_set_signal(SIGILL, sigsegv_handler);
444#    endif /* SIGILL */
445#    ifdef SIGIOT
446  si_set_signal(SIGIOT, sigsegv_handler);
447#    endif /* SIGIOT */
448#    ifdef SIGXCPU
449  si_set_signal(SIGXCPU, (void (*)(int))SIG_IGN);
450#    endif /* SIGIOT */
451  si_set_signal(SIGINT ,sigint_handler);
452#if defined(HPUX_9) || defined(HPUX_10)
453  si_set_signal(SIGCHLD, (void (*)(int))SIG_IGN);
454#endif
455#  endif /* !MSDOS */
456}
457# endif /* SPARC_SUNOS_4 */
458#endif /* linux && __i386__ */
459
460
461#ifndef MSDOS
462/*2
463* signal handler for SIGINT
464*/
465void sigint_handler(int sig)
466{
467  mflush();
468#  ifdef HAVE_FEREAD
469  if (fe_is_raw_tty) fe_temp_reset();
470#  endif /* HAVE_FEREAD */
471  loop
472  {
473    int cnt=0;
474    int c;
475    fprintf(stderr,"// ** Interrupt at cmd:`%s` in line:'%s'\n",
476      Tok2Cmdname(iiOp),my_yylinebuf);
477    if (feGetOptValue(FE_OPT_EMACS) == NULL)
478    {
479      fputs("abort command(a), continue(c) or quit Singular(q) ?",stderr);fflush(stderr);
480      c = fgetc(stdin);
481    }
482    else
483    {
484      c = 'a';
485    }
486   
487    switch(c)
488    {
489#  if defined(MONOM_COUNT) || defined(DIV_COUNT)
490              case 'e':
491#   ifdef MONOM_COUNT
492                extern void ResetMonomCount();
493                ResetMonomCount();
494#   endif /* MONOM_COUNT */
495#   ifdef DIV_COUNT
496                extern void ResetDivCount();
497                ResetDivCount();
498#   endif /* DIV_COUNT */
499                break;
500              case 'o':
501#   ifdef MONOM_COUNT
502                extern void OutputMonomCount();
503                OutputMonomCount();
504#   endif /* COUNT */
505#   ifdef DIV_COUNT
506                extern void OutputDivCount();
507                OutputDivCount();
508#   endif /* DIV_COUNT */
509                break;
510#  endif /* defined(MONOM_COUNT) || defined(DIV_COUNT) */
511      case 'q':
512                m2_end(2);
513      case 'r':
514                longjmp(si_start_jmpbuf,1);
515      case 'b':
516                VoiceBackTrack();
517                break;
518      case 'a':
519                siCntrlc++;
520      case 'c':
521                if (feGetOptValue(FE_OPT_EMACS) == NULL) fgetc(stdin);
522                si_set_signal(SIGINT ,(si_hdl_typ)sigint_handler);
523                return;
524                //siCntrlc ++;
525                //if (siCntrlc>2) si_set_signal(SIGINT,(si_hdl_typ) sigsegv_handler);
526                //else            si_set_signal(SIGINT,(si_hdl_typ) sigint_handler);
527    }
528    cnt++;
529    if(cnt>5) m2_end(2);
530  }
531}
532#endif /* !MSDOS */
533
534#ifndef MSDOS
535//void test_int()
536//{
537//  if (siCntrlc!=0)
538//  {
539//    int saveecho = si_echo;
540//    siCntrlc = FALSE;
541//    si_set_signal(SIGINT ,sigint_handler);
542//    iiDebug();
543//    si_echo = saveecho;
544//  }
545//}
546#endif /* !MSDOS */
547
548#ifdef unix
549# ifndef hpux
550#  ifndef __OPTIMIZE__
551#   ifndef MSDOS
552int si_stop_stack_trace_x;
553#    ifdef CALL_GDB
554static void debug (int method)
555{
556  if (feOptValue(FE_OPT_NO_TTY))
557  {
558    dReportError("Caught Signal 11");
559    return;
560  }
561  int pid;
562  char buf[16];
563  char *args[4] = { "gdb", "Singularg", NULL, NULL };
564
565#     ifdef HAVE_FEREAD
566  if (fe_is_raw_tty) fe_temp_reset();
567#     endif /* HAVE_FEREAD */
568
569  sprintf (buf, "%d", getpid ());
570
571  args[2] = buf;
572
573  pid = fork ();
574  if (pid == 0)
575  {
576    switch (method)
577    {
578      case INTERACTIVE:
579        fprintf (stderr, "debug_stop\n");
580        debug_stop (args);
581        break;
582      case STACK_TRACE:
583        fprintf (stderr, "stack_trace\n");
584        stack_trace (args);
585        break;
586      default:
587        // should not be reached:
588        exit(1);
589    }
590  }
591  else if (pid == -1)
592  {
593    perror ("could not fork");
594    return;
595  }
596
597  si_stop_stack_trace_x = 1;
598  while (si_stop_stack_trace_x) ;
599}
600
601static void debug_stop ( char **args)
602{
603  execvp (args[0], args);
604  perror ("exec failed");
605  _exit (0);
606}
607#    endif /* CALL_GDB */
608
609static int stack_trace_done;
610
611static void stack_trace (char **args)
612{
613  int pid;
614  int in_fd[2];
615  int out_fd[2];
616  fd_set fdset;
617  fd_set readset;
618  struct timeval tv;
619  int sel, index, state;
620  char buffer[256];
621  char c;
622
623  stack_trace_done = 0;
624
625  signal (SIGCHLD, stack_trace_sigchld);
626
627  if ((pipe (in_fd) == -1) || (pipe (out_fd) == -1))
628  {
629    perror ("could open pipe");
630    m2_end(999);
631  }
632
633  pid = fork ();
634  if (pid == 0)
635  {
636    close (0); dup2 (in_fd[0],0);   /* set the stdin to the in pipe */
637    close (1); dup2 (out_fd[1],1);  /* set the stdout to the out pipe */
638    close (2); dup2 (out_fd[1],2);  /* set the stderr to the out pipe */
639
640    execvp (args[0], args);      /* exec gdb */
641    perror ("exec failed");
642    m2_end(999);
643  }
644  else if (pid == -1)
645  {
646    perror ("could not fork");
647    m2_end(999);
648  }
649
650  FD_ZERO (&fdset);
651  FD_SET (out_fd[0], &fdset);
652
653  write (in_fd[1], "backtrace\n", 10);
654  write (in_fd[1], "p si_stop_stack_trace_x = 0\n", 28);
655  write (in_fd[1], "quit\n", 5);
656
657  index = 0;
658  state = 0;
659
660  loop
661  {
662    readset = fdset;
663    tv.tv_sec = 1;
664    tv.tv_usec = 0;
665
666#    ifdef hpux
667    sel = select (FD_SETSIZE, (int *)readset.fds_bits, NULL, NULL, &tv);
668#    else /* hpux */
669    sel = select (FD_SETSIZE, &readset, NULL, NULL, &tv);
670#    endif /* hpux */
671    if (sel == -1)
672      break;
673
674    if ((sel > 0) && (FD_ISSET (out_fd[0], &readset)))
675    {
676      if (read (out_fd[0], &c, 1))
677      {
678        switch (state)
679        {
680          case 0:
681            if (c == '#')
682            {
683              state = 1;
684              index = 0;
685              buffer[index++] = c;
686            }
687            break;
688          case 1:
689            buffer[index++] = c;
690            if ((c == '\n') || (c == '\r'))
691            {
692              buffer[index] = 0;
693              fprintf (stderr, "%s", buffer);
694              state = 0;
695              index = 0;
696            }
697            break;
698          default:
699            break;
700        }
701      }
702    }
703    else if (stack_trace_done)
704      break;
705  }
706
707  close (in_fd[0]);
708  close (in_fd[1]);
709  close (out_fd[0]);
710  close (out_fd[1]);
711  m2_end(0);
712}
713
714static void stack_trace_sigchld (int signum)
715{
716  stack_trace_done = 1;
717}
718
719#   endif /* !MSDOS */
720#  endif /* !__OPTIMIZE__ */
721# endif /* !hpux */
722#endif /* unix */
723
724/* Under HPUX 9, system(...) returns -1 if SIGCHLD does not equal
725   SIG_DFL. However, if it stays at SIG_DFL we get zombie processes
726   for terminated childs generated by fork. Therefors some special treatment
727   is necessary */
728#ifdef HPUX_9
729# undef system
730extern "C" {
731  int  hpux9_system(const char* call)
732  {
733    int ret;
734    si_set_signal(SIGCHLD, (void (*)(int))SIG_DFL);
735    ret = system(call);
736    si_set_signal(SIGCHLD, (void (*)(int))SIG_IGN);
737    return ret;
738  }
739}
740#endif /* HPUX_9 */
Note: See TracBrowser for help on using the repository browser.