source: git/Singular/cntrlc.cc @ 0ec43a

spielwiese
Last change on this file since 0ec43a was 0ec43a, checked in by Hans Schönemann <hannes@…>, 16 years ago
*hannes: gcc 4.2 fixes git-svn-id: file:///usr/local/Singular/svn/trunk@11041 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.57 2008-09-10 09:21:29 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,"Segment fault/Bus error occurred at %lx because of %lx (r:%d)\n"
177                   "please inform the authors\n",
178                   #ifdef __i386__
179                   (long)s.eip,
180                   #else /* x86_64*/
181                   (long)s.rip,
182                   #endif
183                   (long)s.cr2,siRandomStart);
184  }
185#ifdef __OPTIMIZE__
186  if(si_restart<3)
187  {
188    si_restart++;
189    fprintf(stderr,"trying to restart...\n");
190    init_signals();
191    longjmp(si_start_jmpbuf,1);
192  }
193#endif /* __OPTIMIZE__ */
194#ifdef CALL_GDB
195  if (sig!=SIGINT) debug(INTERACTIVE);
196#endif /* CALL_GDB */
197  exit(0);
198}
199
200/*---------------------------------------------------------------------*/
201/**
202 * @brief additional default signal handler
203
204  // some newer Linux version cannot have SIG_IGN for SIGCHLD,
205  // so use this nice routine here:
206  //  SuSe 9.x reports -1 always
207  //  Redhat 9.x/FC x reports sometimes -1
208  // see also: hpux_system
209
210 @param[in] sig
211**/
212/*---------------------------------------------------------------------*/
213void sig_ign_hdl(int sig)
214{
215}
216
217/*2
218* init signal handlers, linux/i386 version
219*/
220void init_signals()
221{
222/*4 signal handler: linux*/
223  if (SIG_ERR==si_set_signal(SIGSEGV,(si_hdl_typ)sigsegv_handler))
224  {
225    PrintS("cannot set signal handler for SEGV\n");
226  }
227  if (SIG_ERR==si_set_signal(SIGFPE, (si_hdl_typ)sigsegv_handler))
228  {
229    PrintS("cannot set signal handler for FPE\n");
230  }
231  if (SIG_ERR==si_set_signal(SIGILL, (si_hdl_typ)sigsegv_handler))
232  {
233    PrintS("cannot set signal handler for ILL\n");
234  }
235  if (SIG_ERR==si_set_signal(SIGIOT, (si_hdl_typ)sigsegv_handler))
236  {
237    PrintS("cannot set signal handler for IOT\n");
238  }
239  if (SIG_ERR==si_set_signal(SIGINT ,(si_hdl_typ)sigint_handler))
240  {
241    PrintS("cannot set signal handler for INT\n");
242  }
243  //si_set_signal(SIGCHLD, (void (*)(int))SIG_IGN);
244  si_set_signal(SIGCHLD, (si_hdl_typ)sig_ign_hdl);
245}
246
247/*---------------------------------------------------------------------*/
248#elif defined(SunOS) /*SPARC_SUNOS*/
249/*2
250* signal handler for run time errors, sparc sunos 4 version
251*/
252void sigsegv_handler(int sig, int code, struct sigcontext *scp, char *addr)
253{
254  fprintf(stderr,"Singular : signal %d, code %d (v: %d/%u):\n",
255    sig,code,SINGULAR_VERSION,feVersionId);
256  if ((sig!=SIGINT)&&(sig!=SIGABRT))
257  {
258    fprintf(stderr,"Segment fault/Bus error occurred at %x (r:%d)\n"
259                   "please inform the authors\n",
260                   (int)addr,siRandomStart);
261  }
262#ifdef __OPTIMIZE__
263  if(si_restart<3)
264  {
265    si_restart++;
266    fprintf(stderr,"trying to restart...\n");
267    init_signals();
268    longjmp(si_start_jmpbuf,1);
269  }
270#endif /* __OPTIMIZE__ */
271#ifdef CALL_GDB
272  if (sig!=SIGINT) debug(STACK_TRACE);
273#endif /* CALL_GDB */
274  exit(0);
275}
276
277/*2
278* init signal handlers, sparc sunos 4 version
279*/
280void init_signals()
281{
282/*4 signal handler:*/
283  si_set_signal(SIGSEGV,sigsegv_handler);
284  si_set_signal(SIGBUS, sigsegv_handler);
285  si_set_signal(SIGFPE, sigsegv_handler);
286  si_set_signal(SIGILL, sigsegv_handler);
287  si_set_signal(SIGIOT, sigsegv_handler);
288  si_set_signal(SIGINT ,sigint_handler);
289  si_set_signal(SIGCHLD, (void (*)(int))SIG_IGN);
290}
291#else
292
293/*---------------------------------------------------------------------*/
294/*2
295* signal handler for run time errors, general version
296*/
297void sigsegv_handler(int sig)
298{
299  fprintf(stderr,"Singular : signal %d (v: %d/%u):\n",
300    sig,SINGULAR_VERSION,feVersionId);
301  if (sig!=SIGINT)
302  {
303    fprintf(stderr,"Segment fault/Bus error occurred (r:%d)\n"
304                   "please inform the authors\n",
305                   siRandomStart);
306  }
307  #ifdef __OPTIMIZE__
308  if(si_restart<3)
309  {
310    si_restart++;
311    fprintf(stderr,"trying to restart...\n");
312    init_signals();
313    longjmp(si_start_jmpbuf,1);
314  }
315  #endif /* __OPTIMIZE__ */
316  #if defined(unix) && !defined(hpux)
317  /* debug(..) does not work under HPUX (because ptrace does not work..) */
318  #ifdef CALL_GDB
319  if (sig!=SIGINT) debug(STACK_TRACE);
320  #endif /* CALL_GDB */
321  #endif /* unix */
322  exit(0);
323}
324
325/*2
326* init signal handlers, general version
327*/
328void init_signals()
329{
330/*4 signal handler:*/
331  si_set_signal(SIGSEGV,(void (*) (int))sigsegv_handler);
332  #ifdef SIGBUS
333  si_set_signal(SIGBUS, sigsegv_handler);
334  #endif /* SIGBUS */
335  #ifdef SIGFPE
336  si_set_signal(SIGFPE, sigsegv_handler);
337  #endif /* SIGFPE */
338  #ifdef SIGILL
339  si_set_signal(SIGILL, sigsegv_handler);
340  #endif /* SIGILL */
341  #ifdef SIGIOT
342  si_set_signal(SIGIOT, sigsegv_handler);
343  #endif /* SIGIOT */
344  #ifdef SIGXCPU
345  si_set_signal(SIGXCPU, (void (*)(int))SIG_IGN);
346  #endif /* SIGIOT */
347  si_set_signal(SIGINT ,sigint_handler);
348  #if defined(HPUX_9) || defined(HPUX_10)
349  si_set_signal(SIGCHLD, (void (*)(int))SIG_IGN);
350  #endif
351}
352#endif
353
354
355/*2
356* signal handler for SIGINT
357*/
358void sigint_handler(int sig)
359{
360  mflush();
361  #ifdef HAVE_FEREAD
362  if (fe_is_raw_tty) fe_temp_reset();
363  #endif /* HAVE_FEREAD */
364  loop
365  {
366    int cnt=0;
367    int c;
368    fprintf(stderr,"// ** Interrupt at cmd:`%s` in line:'%s'\n",
369      Tok2Cmdname(iiOp),my_yylinebuf);
370    if (feGetOptValue(FE_OPT_EMACS) == NULL)
371    {
372      fputs("abort command(a), continue(c) or quit Singular(q) ?",stderr);fflush(stderr);
373      c = fgetc(stdin);
374    }
375    else
376    {
377      c = 'a';
378    }
379
380    switch(c)
381    {
382      case 'q':
383                m2_end(2);
384      case 'r':
385                longjmp(si_start_jmpbuf,1);
386      case 'b':
387                VoiceBackTrack();
388                break;
389      case 'a':
390                siCntrlc++;
391      case 'c':
392                if (feGetOptValue(FE_OPT_EMACS) == NULL) fgetc(stdin);
393                si_set_signal(SIGINT ,(si_hdl_typ)sigint_handler);
394                return;
395                //siCntrlc ++;
396                //if (siCntrlc>2) si_set_signal(SIGINT,(si_hdl_typ) sigsegv_handler);
397                //else            si_set_signal(SIGINT,(si_hdl_typ) sigint_handler);
398    }
399    cnt++;
400    if(cnt>5) m2_end(2);
401  }
402}
403
404//void test_int()
405//{
406//  if (siCntrlc!=0)
407//  {
408//    int saveecho = si_echo;
409//    siCntrlc = FALSE;
410//    si_set_signal(SIGINT ,sigint_handler);
411//    iiDebug();
412//    si_echo = saveecho;
413//  }
414//}
415
416#ifdef unix
417# ifndef hpux
418#  ifndef __OPTIMIZE__
419int si_stop_stack_trace_x;
420#    ifdef CALL_GDB
421static void debug (int method)
422{
423  if (feOptValue(FE_OPT_NO_TTY))
424  {
425    dReportError("Caught Signal 11");
426    return;
427  }
428  int pid;
429  char buf[16];
430  const char * args[4] = { "gdb", "Singularg", NULL, NULL };
431
432  #ifdef HAVE_FEREAD
433  if (fe_is_raw_tty) fe_temp_reset();
434  #endif /* HAVE_FEREAD */
435
436  sprintf (buf, "%d", getpid ());
437
438  args[2] = buf;
439
440  pid = fork ();
441  if (pid == 0)
442  {
443    switch (method)
444    {
445      case INTERACTIVE:
446        fprintf (stderr, "debug_stop\n");
447        debug_stop (args);
448        break;
449      #ifndef __OPTIMIZE__
450      case STACK_TRACE:
451        fprintf (stderr, "stack_trace\n");
452        stack_trace (args);
453        break;
454      #endif
455      default:
456        // should not be reached:
457        exit(1);
458    }
459  }
460  else if (pid == -1)
461  {
462    perror ("could not fork");
463    return;
464  }
465
466  si_stop_stack_trace_x = 1;
467  while (si_stop_stack_trace_x) ;
468}
469
470static void debug_stop (char * const *args)
471{
472  execvp (args[0], args);
473  perror ("exec failed");
474  _exit (0);
475}
476#    endif /* CALL_GDB */
477
478static int stack_trace_done;
479
480static void stack_trace (char * const *args)
481{
482  int pid;
483  int in_fd[2];
484  int out_fd[2];
485  fd_set fdset;
486  fd_set readset;
487  struct timeval tv;
488  int sel, index, state;
489  char buffer[256];
490  char c;
491
492  stack_trace_done = 0;
493
494  signal (SIGCHLD, stack_trace_sigchld);
495
496  if ((pipe (in_fd) == -1) || (pipe (out_fd) == -1))
497  {
498    perror ("could open pipe");
499    m2_end(999);
500  }
501
502  pid = fork ();
503  if (pid == 0)
504  {
505    close (0); dup2 (in_fd[0],0);   /* set the stdin to the in pipe */
506    close (1); dup2 (out_fd[1],1);  /* set the stdout to the out pipe */
507    close (2); dup2 (out_fd[1],2);  /* set the stderr to the out pipe */
508
509    execvp (args[0], args);      /* exec gdb */
510    perror ("exec failed");
511    m2_end(999);
512  }
513  else if (pid == -1)
514  {
515    perror ("could not fork");
516    m2_end(999);
517  }
518
519  FD_ZERO (&fdset);
520  FD_SET (out_fd[0], &fdset);
521
522  write (in_fd[1], "backtrace\n", 10);
523  write (in_fd[1], "p si_stop_stack_trace_x = 0\n", 28);
524  write (in_fd[1], "quit\n", 5);
525
526  index = 0;
527  state = 0;
528
529  loop
530  {
531    readset = fdset;
532    tv.tv_sec = 1;
533    tv.tv_usec = 0;
534
535#    ifdef hpux
536    sel = select (FD_SETSIZE, (int *)readset.fds_bits, NULL, NULL, &tv);
537#    else /* hpux */
538    sel = select (FD_SETSIZE, &readset, NULL, NULL, &tv);
539#    endif /* hpux */
540    if (sel == -1)
541      break;
542
543    if ((sel > 0) && (FD_ISSET (out_fd[0], &readset)))
544    {
545      if (read (out_fd[0], &c, 1))
546      {
547        switch (state)
548        {
549          case 0:
550            if (c == '#')
551            {
552              state = 1;
553              index = 0;
554              buffer[index++] = c;
555            }
556            break;
557          case 1:
558            buffer[index++] = c;
559            if ((c == '\n') || (c == '\r'))
560            {
561              buffer[index] = 0;
562              fprintf (stderr, "%s", buffer);
563              state = 0;
564              index = 0;
565            }
566            break;
567          default:
568            break;
569        }
570      }
571    }
572    else if (stack_trace_done)
573      break;
574  }
575
576  close (in_fd[0]);
577  close (in_fd[1]);
578  close (out_fd[0]);
579  close (out_fd[1]);
580  m2_end(0);
581}
582
583static void stack_trace_sigchld (int signum)
584{
585  stack_trace_done = 1;
586}
587
588#  endif /* !__OPTIMIZE__ */
589# endif /* !hpux */
590#endif /* unix */
591
592/* Under HPUX 9, system(...) returns -1 if SIGCHLD does not equal
593   SIG_DFL. However, if it stays at SIG_DFL we get zombie processes
594   for terminated childs generated by fork. Therefors some special treatment
595   is necessary */
596#ifdef HPUX_9
597# undef system
598extern "C" {
599  int  hpux9_system(const char* call)
600  {
601    int ret;
602    si_set_signal(SIGCHLD, (void (*)(int))SIG_DFL);
603    ret = system(call);
604    si_set_signal(SIGCHLD, (void (*)(int))SIG_IGN);
605    return ret;
606  }
607}
608#endif /* HPUX_9 */
Note: See TracBrowser for help on using the repository browser.