source: git/Singular/cntrlc.cc @ ffc237

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