source: git/Singular/cntrlc.cc @ 28fc7b

spielwiese
Last change on this file since 28fc7b was 28fc7b, checked in by Hans Schönemann <hannes@…>, 18 years ago
*hannes: segv fix git-svn-id: file:///usr/local/Singular/svn/trunk@9440 2c84dea3-7e68-4137-9b89-c4e89433aadc
  • Property mode set to 100644
File size: 17.0 KB
Line 
1/****************************************
2*  Computer Algebra System SINGULAR     *
3****************************************/
4/* $Id: cntrlc.cc,v 1.51 2006-10-04 12:40:58 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)
164#define HAVE_SIGSTRUCT
165#endif
166
167
168#if defined(linux) && defined(HAVE_SIGSTRUCT)
169/*2---------------------------------------------------------------------*/
170/**
171 * @brief signal handler for run time errors, linux/i386 version
172
173 @param[in] sig     
174 @param[in] s   
175**/
176/*---------------------------------------------------------------------*/
177void sigsegv_handler(int sig, sigcontext s)
178{
179  fprintf(stderr,"Singular : signal %d (v: %d/%u):\n",sig,SINGULAR_VERSION,feVersionId);
180  if (sig!=SIGINT)
181  {
182    fprintf(stderr,"Segment fault/Bus error occurred at %x because of %x (r:%d)\n"
183                   "please inform the authors\n",
184                   #ifdef __i386__
185                   (long)s.eip,
186                   #else /* x86_64*/
187                   (long)s.rip,
188                   #endif
189                   (long)s.cr2,siRandomStart);
190  }
191# ifdef __OPTIMIZE__
192  if(si_restart<3)
193  {
194    si_restart++;
195    fprintf(stderr,"trying to restart...\n");
196    init_signals();
197    longjmp(si_start_jmpbuf,1);
198  }
199# endif /* __OPTIMIZE__ */
200# ifdef CALL_GDB
201  if (sig!=SIGINT) debug(INTERACTIVE);
202# endif /* CALL_GDB */
203  exit(0);
204}
205
206/*---------------------------------------------------------------------*/
207/**
208 * @brief additional default signal handler
209
210  // some newer Linux version cannot have SIG_IGN for SIGCHLD,
211  // so use this nice routine here:
212  //  SuSe 9.x reports -1 always
213  //  Redhat 9.x/FC x reports sometimes -1
214  // see also: hpux_system
215
216 @param[in] sig     
217**/
218/*---------------------------------------------------------------------*/
219void sig_ign_hdl(int sig)
220{
221}
222
223# ifdef PAGE_TEST
224#  ifndef PAGE_INTERRUPT_TIME
225#   define PAGE_INTERRUPT_TIME 1
226#  endif
227
228/*---------------------------------------------------------------------*/
229/**
230 * @brief signal handler for segmentation faults
231
232 @param[in] sig     
233 @param[in] s   
234**/
235/*---------------------------------------------------------------------*/
236void sig11_handler(int sig, sigcontext s)
237{
238  unsigned long base =(unsigned long)(s.cr2&(~4095));
239  int i;
240  i=mmPage_tab_ind-1;
241  while (mmPage_tab[i]!=base) i--;
242  mmUse_tab[i]='1';
243  mmPage_tab_acc++;
244  mmPage_AllowAccess((void *)base);
245  si_set_signal(SIGSEGV,(si_hdl_typ)sig11_handler);
246}
247
248/*---------------------------------------------------------------------*/
249/**
250 * @brief signal handler for alarm signals
251
252 @param[in] sig     
253 @param[in] s   
254**/
255/*---------------------------------------------------------------------*/
256void sigalarm_handler(int sig, sigcontext s)
257{
258  int i=mmPage_tab_ind-1;
259  mmWriteStat();
260  for(;i>=0;i--)
261  {
262    mmPage_DenyAccess((void *)mmPage_tab[i]);
263  }
264  struct itimerval t,o;
265  memset(&t,0,sizeof(t));
266  t.it_value.tv_sec     =(unsigned)0;
267  t.it_value.tv_usec    =(unsigned) PAGE_INTERRUPT_TIME;
268  o.it_value.tv_sec     =(unsigned)0;
269  o.it_value.tv_usec    =(unsigned)PAGE_INTERRUPT_TIME;
270  setitimer(ITIMER_VIRTUAL,&t,&o);
271  si_set_signal(SIGVTALRM,(si_hdl_typ)sigalarm_handler);
272}
273#endif /* PAGE_TEST */
274
275/*2
276* init signal handlers, linux/i386 version
277*/
278void init_signals()
279{
280/*4 signal handler: linux*/
281# ifdef PAGE_TEST
282  si_set_signal(SIGSEGV,(si_hdl_typ)sig11_handler);
283  struct itimerval t,o;
284  memset(&t,0,sizeof(t));
285  t.it_value.tv_sec     =(unsigned)0;
286  t.it_value.tv_usec    =(unsigned)PAGE_INTERRUPT_TIME;
287  o.it_value.tv_sec     =(unsigned)0;
288  o.it_value.tv_usec    =(unsigned)PAGE_INTERRUPT_TIME;
289  setitimer(ITIMER_VIRTUAL,&t,&o);
290  si_set_signal(SIGVTALRM,(si_hdl_typ)sigalarm_handler);
291# else /* PAGE_TEST */
292  if (SIG_ERR==si_set_signal(SIGSEGV,(si_hdl_typ)sigsegv_handler))
293  {
294    PrintS("cannot set signal handler for SEGV\n");
295  }
296# endif /* PAGE_TEST */
297  if (SIG_ERR==si_set_signal(SIGFPE, (si_hdl_typ)sigsegv_handler))
298  {
299    PrintS("cannot set signal handler for FPE\n");
300  }
301  if (SIG_ERR==si_set_signal(SIGILL, (si_hdl_typ)sigsegv_handler))
302  {
303    PrintS("cannot set signal handler for ILL\n");
304  }
305  if (SIG_ERR==si_set_signal(SIGIOT, (si_hdl_typ)sigsegv_handler))
306  {
307    PrintS("cannot set signal handler for IOT\n");
308  }
309  if (SIG_ERR==si_set_signal(SIGINT ,(si_hdl_typ)sigint_handler))
310  {
311    PrintS("cannot set signal handler for INT\n");
312  }
313  //si_set_signal(SIGCHLD, (void (*)(int))SIG_IGN);
314  si_set_signal(SIGCHLD, (si_hdl_typ)sig_ign_hdl);
315}
316
317#else /* linux && __i386__ */
318/*---------------------------------------------------------------------*/
319/*-- SPARC_SUNOS_4 ---*/
320# ifdef SPARC_SUNOS_4
321/*2
322* signal handler for run time errors, sparc sunos 4 version
323*/
324void sigsegv_handler(int sig, int code, struct sigcontext *scp, char *addr)
325{
326  fprintf(stderr,"Singular : signal %d, code %d (v: %d/%u):\n",
327    sig,code,SINGULAR_VERSION,feVersionId);
328  if ((sig!=SIGINT)&&(sig!=SIGABRT))
329  {
330    fprintf(stderr,"Segment fault/Bus error occurred at %x (r:%d)\n"
331                   "please inform the authors\n",
332                   (int)addr,siRandomStart);
333  }
334#  ifdef __OPTIMIZE__
335  if(si_restart<3)
336  {
337    si_restart++;
338    fprintf(stderr,"trying to restart...\n");
339    init_signals();
340    longjmp(si_start_jmpbuf,1);
341  }
342#  endif /* __OPTIMIZE__ */
343#  ifdef CALL_GDB
344  if (sig!=SIGINT) debug(STACK_TRACE);
345#  endif /* CALL_GDB */
346  exit(0);
347}
348
349/*2
350* init signal handlers, sparc sunos 4 version
351*/
352void init_signals()
353{
354/*4 signal handler:*/
355  si_set_signal(SIGSEGV,sigsegv_handler);
356  si_set_signal(SIGBUS, sigsegv_handler);
357  si_set_signal(SIGFPE, sigsegv_handler);
358  si_set_signal(SIGILL, sigsegv_handler);
359  si_set_signal(SIGIOT, sigsegv_handler);
360  si_set_signal(SIGINT ,sigint_handler);
361  si_set_signal(SIGCHLD, (void (*)(int))SIG_IGN);
362}
363# else /* SPARC_SUNOS_4 */
364
365/*---------------------------------------------------------------------*/
366/*2
367* signal handler for run time errors, general version
368*/
369void sigsegv_handler(int sig)
370{
371  fprintf(stderr,"Singular : signal %d (v: %d/%u):\n",
372    sig,SINGULAR_VERSION,feVersionId);
373  if (sig!=SIGINT)
374  {
375    fprintf(stderr,"Segment fault/Bus error occurred (r:%d)\n"
376                   "please inform the authors\n",
377                   siRandomStart);
378  }
379#   ifdef __OPTIMIZE__
380  if(si_restart<3)
381  {
382    si_restart++;
383    fprintf(stderr,"trying to restart...\n");
384    init_signals();
385    longjmp(si_start_jmpbuf,1);
386  }
387#   endif /* __OPTIMIZE__ */
388#   ifdef unix
389#    ifndef hpux
390/* debug(..) does not work under HPUX (because ptrace does not work..) */
391#     ifdef CALL_GDB
392#      ifndef MSDOS
393  if (sig!=SIGINT) debug(STACK_TRACE);
394#      endif /* MSDOS */
395#     endif /* CALL_GDB */
396#    endif /* !hpux */
397#   endif /* unix */
398  exit(0);
399}
400
401/*2
402* init signal handlers, general version
403*/
404void init_signals()
405{
406#  ifndef MSDOS
407/* signals are not implemented in DJGCC */
408/*4 signal handler:*/
409  si_set_signal(SIGSEGV,(void (*) (int))sigsegv_handler);
410#    ifdef SIGBUS
411  si_set_signal(SIGBUS, sigsegv_handler);
412#    endif /* SIGBUS */
413#    ifdef SIGFPE
414  si_set_signal(SIGFPE, sigsegv_handler);
415#    endif /* SIGFPE */
416#    ifdef SIGILL
417  si_set_signal(SIGILL, sigsegv_handler);
418#    endif /* SIGILL */
419#    ifdef SIGIOT
420  si_set_signal(SIGIOT, sigsegv_handler);
421#    endif /* SIGIOT */
422#    ifdef SIGXCPU
423  si_set_signal(SIGXCPU, (void (*)(int))SIG_IGN);
424#    endif /* SIGIOT */
425  si_set_signal(SIGINT ,sigint_handler);
426#if defined(HPUX_9) || defined(HPUX_10)
427  si_set_signal(SIGCHLD, (void (*)(int))SIG_IGN);
428#endif
429#  endif /* !MSDOS */
430}
431# endif /* SPARC_SUNOS_4 */
432#endif /* linux && __i386__ */
433
434
435#ifndef MSDOS
436/*2
437* signal handler for SIGINT
438*/
439void sigint_handler(int sig)
440{
441  mflush();
442#  ifdef HAVE_FEREAD
443  if (fe_is_raw_tty) fe_temp_reset();
444#  endif /* HAVE_FEREAD */
445  loop
446  {
447    int cnt=0;
448    int c;
449    fprintf(stderr,"// ** Interrupt at cmd:`%s` in line:'%s'\n",
450      Tok2Cmdname(iiOp),my_yylinebuf);
451    if (feGetOptValue(FE_OPT_EMACS) == NULL)
452    {
453      fputs("abort command(a), continue(c) or quit Singular(q) ?",stderr);fflush(stderr);
454      c = fgetc(stdin);
455    }
456    else
457    {
458      c = 'a';
459    }
460   
461    switch(c)
462    {
463#  if defined(MONOM_COUNT) || defined(DIV_COUNT)
464              case 'e':
465#   ifdef MONOM_COUNT
466                extern void ResetMonomCount();
467                ResetMonomCount();
468#   endif /* MONOM_COUNT */
469#   ifdef DIV_COUNT
470                extern void ResetDivCount();
471                ResetDivCount();
472#   endif /* DIV_COUNT */
473                break;
474              case 'o':
475#   ifdef MONOM_COUNT
476                extern void OutputMonomCount();
477                OutputMonomCount();
478#   endif /* COUNT */
479#   ifdef DIV_COUNT
480                extern void OutputDivCount();
481                OutputDivCount();
482#   endif /* DIV_COUNT */
483                break;
484#  endif /* defined(MONOM_COUNT) || defined(DIV_COUNT) */
485      case 'q':
486                m2_end(2);
487      case 'r':
488                longjmp(si_start_jmpbuf,1);
489      case 'b':
490                VoiceBackTrack();
491                break;
492      case 'a':
493                siCntrlc++;
494      case 'c':
495                if (feGetOptValue(FE_OPT_EMACS) == NULL) fgetc(stdin);
496                si_set_signal(SIGINT ,(si_hdl_typ)sigint_handler);
497                return;
498                //siCntrlc ++;
499                //if (siCntrlc>2) si_set_signal(SIGINT,(si_hdl_typ) sigsegv_handler);
500                //else            si_set_signal(SIGINT,(si_hdl_typ) sigint_handler);
501    }
502    cnt++;
503    if(cnt>5) m2_end(2);
504  }
505}
506#endif /* !MSDOS */
507
508#ifndef MSDOS
509//void test_int()
510//{
511//  if (siCntrlc!=0)
512//  {
513//    int saveecho = si_echo;
514//    siCntrlc = FALSE;
515//    si_set_signal(SIGINT ,sigint_handler);
516//    iiDebug();
517//    si_echo = saveecho;
518//  }
519//}
520#endif /* !MSDOS */
521
522#ifdef unix
523# ifndef hpux
524#  ifndef __OPTIMIZE__
525#   ifndef MSDOS
526int si_stop_stack_trace_x;
527#    ifdef CALL_GDB
528static void debug (int method)
529{
530  if (feOptValue(FE_OPT_NO_TTY))
531  {
532    dReportError("Caught Signal 11");
533    return;
534  }
535  int pid;
536  char buf[16];
537  char *args[4] = { "gdb", "Singularg", NULL, NULL };
538
539#     ifdef HAVE_FEREAD
540  if (fe_is_raw_tty) fe_temp_reset();
541#     endif /* HAVE_FEREAD */
542
543  sprintf (buf, "%d", getpid ());
544
545  args[2] = buf;
546
547  pid = fork ();
548  if (pid == 0)
549  {
550    switch (method)
551    {
552      case INTERACTIVE:
553        fprintf (stderr, "debug_stop\n");
554        debug_stop (args);
555        break;
556      case STACK_TRACE:
557        fprintf (stderr, "stack_trace\n");
558        stack_trace (args);
559        break;
560      default:
561        // should not be reached:
562        exit(1);
563    }
564  }
565  else if (pid == -1)
566  {
567    perror ("could not fork");
568    return;
569  }
570
571  si_stop_stack_trace_x = 1;
572  while (si_stop_stack_trace_x) ;
573}
574
575static void debug_stop ( char **args)
576{
577  execvp (args[0], args);
578  perror ("exec failed");
579  _exit (0);
580}
581#    endif /* CALL_GDB */
582
583static int stack_trace_done;
584
585static void stack_trace (char **args)
586{
587  int pid;
588  int in_fd[2];
589  int out_fd[2];
590  fd_set fdset;
591  fd_set readset;
592  struct timeval tv;
593  int sel, index, state;
594  char buffer[256];
595  char c;
596
597  stack_trace_done = 0;
598
599  signal (SIGCHLD, stack_trace_sigchld);
600
601  if ((pipe (in_fd) == -1) || (pipe (out_fd) == -1))
602  {
603    perror ("could open pipe");
604    m2_end(999);
605  }
606
607  pid = fork ();
608  if (pid == 0)
609  {
610    close (0); dup2 (in_fd[0],0);   /* set the stdin to the in pipe */
611    close (1); dup2 (out_fd[1],1);  /* set the stdout to the out pipe */
612    close (2); dup2 (out_fd[1],2);  /* set the stderr to the out pipe */
613
614    execvp (args[0], args);      /* exec gdb */
615    perror ("exec failed");
616    m2_end(999);
617  }
618  else if (pid == -1)
619  {
620    perror ("could not fork");
621    m2_end(999);
622  }
623
624  FD_ZERO (&fdset);
625  FD_SET (out_fd[0], &fdset);
626
627  write (in_fd[1], "backtrace\n", 10);
628  write (in_fd[1], "p si_stop_stack_trace_x = 0\n", 28);
629  write (in_fd[1], "quit\n", 5);
630
631  index = 0;
632  state = 0;
633
634  loop
635  {
636    readset = fdset;
637    tv.tv_sec = 1;
638    tv.tv_usec = 0;
639
640#    ifdef hpux
641    sel = select (FD_SETSIZE, (int *)readset.fds_bits, NULL, NULL, &tv);
642#    else /* hpux */
643    sel = select (FD_SETSIZE, &readset, NULL, NULL, &tv);
644#    endif /* hpux */
645    if (sel == -1)
646      break;
647
648    if ((sel > 0) && (FD_ISSET (out_fd[0], &readset)))
649    {
650      if (read (out_fd[0], &c, 1))
651      {
652        switch (state)
653        {
654          case 0:
655            if (c == '#')
656            {
657              state = 1;
658              index = 0;
659              buffer[index++] = c;
660            }
661            break;
662          case 1:
663            buffer[index++] = c;
664            if ((c == '\n') || (c == '\r'))
665            {
666              buffer[index] = 0;
667              fprintf (stderr, "%s", buffer);
668              state = 0;
669              index = 0;
670            }
671            break;
672          default:
673            break;
674        }
675      }
676    }
677    else if (stack_trace_done)
678      break;
679  }
680
681  close (in_fd[0]);
682  close (in_fd[1]);
683  close (out_fd[0]);
684  close (out_fd[1]);
685  m2_end(0);
686}
687
688static void stack_trace_sigchld (int signum)
689{
690  stack_trace_done = 1;
691}
692
693#   endif /* !MSDOS */
694#  endif /* !__OPTIMIZE__ */
695# endif /* !hpux */
696#endif /* unix */
697
698/* Under HPUX 9, system(...) returns -1 if SIGCHLD does not equal
699   SIG_DFL. However, if it stays at SIG_DFL we get zombie processes
700   for terminated childs generated by fork. Therefors some special treatment
701   is necessary */
702#ifdef HPUX_9
703# undef system
704extern "C" {
705  int  hpux9_system(const char* call)
706  {
707    int ret;
708    si_set_signal(SIGCHLD, (void (*)(int))SIG_DFL);
709    ret = system(call);
710    si_set_signal(SIGCHLD, (void (*)(int))SIG_IGN);
711    return ret;
712  }
713}
714#endif /* HPUX_9 */
Note: See TracBrowser for help on using the repository browser.