source: git/Singular/cntrlc.cc @ 337d5b

spielwiese
Last change on this file since 337d5b was 337d5b, checked in by Hans Schönemann <hannes@…>, 17 years ago
*hannes: removed old debug stuff, enabled sigsegv git-svn-id: file:///usr/local/Singular/svn/trunk@9944 2c84dea3-7e68-4137-9b89-c4e89433aadc
  • Property mode set to 100644
File size: 14.1 KB
Line 
1/****************************************
2*  Computer Algebra System SINGULAR     *
3****************************************/
4/* $Id: cntrlc.cc,v 1.53 2007-03-13 18:54:15 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 **);
64 #endif
65 #ifndef __OPTIMIZE__
66   static void stack_trace (char **);
67   static void stack_trace_sigchld (int);
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 *---------------------------------------------------------------------*/
90#ifndef MSDOS
91/* signals are not implemented in DJGCC */
92void sigint_handler(int sig);
93#endif /* MSDOS */
94
95si_hdl_typ si_set_signal ( int sig, si_hdl_typ signal_handler);
96
97/*---------------------------------------------------------------------*/
98/**
99 * @brief meta function for binding a signal to an handler
100
101 @param[in] sig             Signal number
102 @param[in] signal_handler  Pointer to signal handler
103
104 @return value of signal()
105**/
106/*---------------------------------------------------------------------*/
107si_hdl_typ si_set_signal (
108  int sig,
109  si_hdl_typ signal_handler
110  )
111{
112  si_hdl_typ retval=signal (sig, (si_hdl_typ)signal_handler);
113  if (retval == SIG_ERR)
114  {
115     fprintf(stderr, "Unable to init signal %d ... exiting...\n", sig);
116  }
117#ifdef HAVE_SIGINTERRUPT
118  siginterrupt(sig, 1);
119#endif
120  return retval;
121}                               /* si_set_signal */
122
123
124/*---------------------------------------------------------------------*/
125#if defined(ix86_Linux)
126  #if defined(HAVE_SIGCONTEXT) || defined(HAVE_ASM_SIGCONTEXT_H)
127  #include <asm/sigcontext.h>
128  #else
129struct sigcontext_struct {
130        unsigned short gs, __gsh;
131        unsigned short fs, __fsh;
132        unsigned short es, __esh;
133        unsigned short ds, __dsh;
134        unsigned long edi;
135        unsigned long esi;
136        unsigned long ebp;
137        unsigned long esp;
138        unsigned long ebx;
139        unsigned long edx;
140        unsigned long ecx;
141        unsigned long eax;
142        unsigned long trapno;
143        unsigned long err;
144        unsigned long eip;
145        unsigned short cs, __csh;
146        unsigned long eflags;
147        unsigned long esp_at_signal;
148        unsigned short ss, __ssh;
149        unsigned long i387;
150        unsigned long oldmask;
151        unsigned long cr2;
152};
153#endif
154#define HAVE_SIGSTRUCT
155typedef struct sigcontext_struct sigcontext;
156#endif
157
158#if defined(x86_64_Linux)
159#define HAVE_SIGSTRUCT
160#endif
161
162
163#if defined(HAVE_SIGSTRUCT)
164/*2---------------------------------------------------------------------*/
165/**
166 * @brief signal handler for run time errors, linux/i386, x86_64 version
167
168 @param[in] sig
169 @param[in] s
170**/
171/*---------------------------------------------------------------------*/
172void sigsegv_handler(int sig, sigcontext s)
173{
174  fprintf(stderr,"Singular : signal %d (v: %d/%u):\n",sig,SINGULAR_VERSION,feVersionId);
175  if (sig!=SIGINT)
176  {
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,"Segment fault/Bus error occurred at %x (r:%d)\n"
260                   "please inform the authors\n",
261                   (int)addr,siRandomStart);
262  }
263#ifdef __OPTIMIZE__
264  if(si_restart<3)
265  {
266    si_restart++;
267    fprintf(stderr,"trying to restart...\n");
268    init_signals();
269    longjmp(si_start_jmpbuf,1);
270  }
271#endif /* __OPTIMIZE__ */
272#ifdef CALL_GDB
273  if (sig!=SIGINT) debug(STACK_TRACE);
274#endif /* CALL_GDB */
275  exit(0);
276}
277
278/*2
279* init signal handlers, sparc sunos 4 version
280*/
281void init_signals()
282{
283/*4 signal handler:*/
284  si_set_signal(SIGSEGV,sigsegv_handler);
285  si_set_signal(SIGBUS, sigsegv_handler);
286  si_set_signal(SIGFPE, sigsegv_handler);
287  si_set_signal(SIGILL, sigsegv_handler);
288  si_set_signal(SIGIOT, sigsegv_handler);
289  si_set_signal(SIGINT ,sigint_handler);
290  si_set_signal(SIGCHLD, (void (*)(int))SIG_IGN);
291}
292#else
293
294/*---------------------------------------------------------------------*/
295/*2
296* signal handler for run time errors, general version
297*/
298void sigsegv_handler(int sig)
299{
300  fprintf(stderr,"Singular : signal %d (v: %d/%u):\n",
301    sig,SINGULAR_VERSION,feVersionId);
302  if (sig!=SIGINT)
303  {
304    fprintf(stderr,"Segment fault/Bus error occurred (r:%d)\n"
305                   "please inform the authors\n",
306                   siRandomStart);
307  }
308  #ifdef __OPTIMIZE__
309  if(si_restart<3)
310  {
311    si_restart++;
312    fprintf(stderr,"trying to restart...\n");
313    init_signals();
314    longjmp(si_start_jmpbuf,1);
315  }
316  #endif /* __OPTIMIZE__ */
317  #if defined(unix) && !defined(hpux)
318  /* debug(..) does not work under HPUX (because ptrace does not work..) */
319  #ifdef CALL_GDB
320  #ifndef MSDOS
321  if (sig!=SIGINT) debug(STACK_TRACE);
322  #endif /* MSDOS */
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  #ifndef MSDOS
334/* signals are not implemented in DJGCC */
335/*4 signal handler:*/
336  si_set_signal(SIGSEGV,(void (*) (int))sigsegv_handler);
337  #ifdef SIGBUS
338  si_set_signal(SIGBUS, sigsegv_handler);
339  #endif /* SIGBUS */
340  #ifdef SIGFPE
341  si_set_signal(SIGFPE, sigsegv_handler);
342  #endif /* SIGFPE */
343  #ifdef SIGILL
344  si_set_signal(SIGILL, sigsegv_handler);
345  #endif /* SIGILL */
346  #ifdef SIGIOT
347  si_set_signal(SIGIOT, sigsegv_handler);
348  #endif /* SIGIOT */
349  #ifdef SIGXCPU
350  si_set_signal(SIGXCPU, (void (*)(int))SIG_IGN);
351  #endif /* SIGIOT */
352  si_set_signal(SIGINT ,sigint_handler);
353  #if defined(HPUX_9) || defined(HPUX_10)
354  si_set_signal(SIGCHLD, (void (*)(int))SIG_IGN);
355  #endif
356  #endif /* !MSDOS */
357}
358#endif
359
360
361#ifndef MSDOS
362/*2
363* signal handler for SIGINT
364*/
365void sigint_handler(int sig)
366{
367  mflush();
368  #ifdef HAVE_FEREAD
369  if (fe_is_raw_tty) fe_temp_reset();
370  #endif /* HAVE_FEREAD */
371  loop
372  {
373    int cnt=0;
374    int c;
375    fprintf(stderr,"// ** Interrupt at cmd:`%s` in line:'%s'\n",
376      Tok2Cmdname(iiOp),my_yylinebuf);
377    if (feGetOptValue(FE_OPT_EMACS) == NULL)
378    {
379      fputs("abort command(a), continue(c) or quit Singular(q) ?",stderr);fflush(stderr);
380      c = fgetc(stdin);
381    }
382    else
383    {
384      c = 'a';
385    }
386
387    switch(c)
388    {
389      case 'q':
390                m2_end(2);
391      case 'r':
392                longjmp(si_start_jmpbuf,1);
393      case 'b':
394                VoiceBackTrack();
395                break;
396      case 'a':
397                siCntrlc++;
398      case 'c':
399                if (feGetOptValue(FE_OPT_EMACS) == NULL) fgetc(stdin);
400                si_set_signal(SIGINT ,(si_hdl_typ)sigint_handler);
401                return;
402                //siCntrlc ++;
403                //if (siCntrlc>2) si_set_signal(SIGINT,(si_hdl_typ) sigsegv_handler);
404                //else            si_set_signal(SIGINT,(si_hdl_typ) sigint_handler);
405    }
406    cnt++;
407    if(cnt>5) m2_end(2);
408  }
409}
410#endif /* !MSDOS */
411
412#ifndef MSDOS
413//void test_int()
414//{
415//  if (siCntrlc!=0)
416//  {
417//    int saveecho = si_echo;
418//    siCntrlc = FALSE;
419//    si_set_signal(SIGINT ,sigint_handler);
420//    iiDebug();
421//    si_echo = saveecho;
422//  }
423//}
424#endif /* !MSDOS */
425
426#ifdef unix
427# ifndef hpux
428#  ifndef __OPTIMIZE__
429#   ifndef MSDOS
430int si_stop_stack_trace_x;
431#    ifdef CALL_GDB
432static void debug (int method)
433{
434  if (feOptValue(FE_OPT_NO_TTY))
435  {
436    dReportError("Caught Signal 11");
437    return;
438  }
439  int pid;
440  char buf[16];
441  char *args[4] = { "gdb", "Singularg", NULL, NULL };
442
443  #ifdef HAVE_FEREAD
444  if (fe_is_raw_tty) fe_temp_reset();
445  #endif /* HAVE_FEREAD */
446
447  sprintf (buf, "%d", getpid ());
448
449  args[2] = buf;
450
451  pid = fork ();
452  if (pid == 0)
453  {
454    switch (method)
455    {
456      case INTERACTIVE:
457        fprintf (stderr, "debug_stop\n");
458        debug_stop (args);
459        break;
460      case STACK_TRACE:
461        fprintf (stderr, "stack_trace\n");
462        stack_trace (args);
463        break;
464      default:
465        // should not be reached:
466        exit(1);
467    }
468  }
469  else if (pid == -1)
470  {
471    perror ("could not fork");
472    return;
473  }
474
475  si_stop_stack_trace_x = 1;
476  while (si_stop_stack_trace_x) ;
477}
478
479static void debug_stop ( char **args)
480{
481  execvp (args[0], args);
482  perror ("exec failed");
483  _exit (0);
484}
485#    endif /* CALL_GDB */
486
487static int stack_trace_done;
488
489static void stack_trace (char **args)
490{
491  int pid;
492  int in_fd[2];
493  int out_fd[2];
494  fd_set fdset;
495  fd_set readset;
496  struct timeval tv;
497  int sel, index, state;
498  char buffer[256];
499  char c;
500
501  stack_trace_done = 0;
502
503  signal (SIGCHLD, stack_trace_sigchld);
504
505  if ((pipe (in_fd) == -1) || (pipe (out_fd) == -1))
506  {
507    perror ("could open pipe");
508    m2_end(999);
509  }
510
511  pid = fork ();
512  if (pid == 0)
513  {
514    close (0); dup2 (in_fd[0],0);   /* set the stdin to the in pipe */
515    close (1); dup2 (out_fd[1],1);  /* set the stdout to the out pipe */
516    close (2); dup2 (out_fd[1],2);  /* set the stderr to the out pipe */
517
518    execvp (args[0], args);      /* exec gdb */
519    perror ("exec failed");
520    m2_end(999);
521  }
522  else if (pid == -1)
523  {
524    perror ("could not fork");
525    m2_end(999);
526  }
527
528  FD_ZERO (&fdset);
529  FD_SET (out_fd[0], &fdset);
530
531  write (in_fd[1], "backtrace\n", 10);
532  write (in_fd[1], "p si_stop_stack_trace_x = 0\n", 28);
533  write (in_fd[1], "quit\n", 5);
534
535  index = 0;
536  state = 0;
537
538  loop
539  {
540    readset = fdset;
541    tv.tv_sec = 1;
542    tv.tv_usec = 0;
543
544#    ifdef hpux
545    sel = select (FD_SETSIZE, (int *)readset.fds_bits, NULL, NULL, &tv);
546#    else /* hpux */
547    sel = select (FD_SETSIZE, &readset, NULL, NULL, &tv);
548#    endif /* hpux */
549    if (sel == -1)
550      break;
551
552    if ((sel > 0) && (FD_ISSET (out_fd[0], &readset)))
553    {
554      if (read (out_fd[0], &c, 1))
555      {
556        switch (state)
557        {
558          case 0:
559            if (c == '#')
560            {
561              state = 1;
562              index = 0;
563              buffer[index++] = c;
564            }
565            break;
566          case 1:
567            buffer[index++] = c;
568            if ((c == '\n') || (c == '\r'))
569            {
570              buffer[index] = 0;
571              fprintf (stderr, "%s", buffer);
572              state = 0;
573              index = 0;
574            }
575            break;
576          default:
577            break;
578        }
579      }
580    }
581    else if (stack_trace_done)
582      break;
583  }
584
585  close (in_fd[0]);
586  close (in_fd[1]);
587  close (out_fd[0]);
588  close (out_fd[1]);
589  m2_end(0);
590}
591
592static void stack_trace_sigchld (int signum)
593{
594  stack_trace_done = 1;
595}
596
597#   endif /* !MSDOS */
598#  endif /* !__OPTIMIZE__ */
599# endif /* !hpux */
600#endif /* unix */
601
602/* Under HPUX 9, system(...) returns -1 if SIGCHLD does not equal
603   SIG_DFL. However, if it stays at SIG_DFL we get zombie processes
604   for terminated childs generated by fork. Therefors some special treatment
605   is necessary */
606#ifdef HPUX_9
607# undef system
608extern "C" {
609  int  hpux9_system(const char* call)
610  {
611    int ret;
612    si_set_signal(SIGCHLD, (void (*)(int))SIG_DFL);
613    ret = system(call);
614    si_set_signal(SIGCHLD, (void (*)(int))SIG_IGN);
615    return ret;
616  }
617}
618#endif /* HPUX_9 */
Note: See TracBrowser for help on using the repository browser.