source: git/Singular/cntrlc.cc @ 7626c5f

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