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

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