source: git/Singular/cntrlc.cc @ 6c22988

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