source: git/Singular/cntrlc.cc @ 762407

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