source: git/Singular/cntrlc.cc @ 561aa2

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