source: git/Singular/cntrlc.cc @ 7c96c03

spielwiese
Last change on this file since 7c96c03 was 7c96c03, checked in by Hans Schönemann <hannes@…>, 18 years ago
*hannes: syntax fixed git-svn-id: file:///usr/local/Singular/svn/trunk@7894 2c84dea3-7e68-4137-9b89-c4e89433aadc
  • Property mode set to 100644
File size: 17.3 KB
Line 
1/****************************************
2*  Computer Algebra System SINGULAR     *
3****************************************/
4/* $Id: cntrlc.cc,v 1.45 2005-04-25 13:25:46 Singular Exp $ */
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 "mod2.h"
19#include "omalloc.h"
20#include "tok.h"
21#include "ipshell.h"
22#include "febase.h"
23#include "cntrlc.h"
24#include "polys.h"
25#include "feOpt.h"
26#include "version.h"
27#ifdef PAGE_TEST
28#include "page.h"
29#endif /* PAGE_TEST */
30
31
32/* undef, if you don't want GDB to come up on error */
33
34#if !defined(__alpha)
35#define CALL_GDB
36#endif
37
38#if defined(__OPTIMIZE__) && defined(CALL_GDB)
39#undef CALL_GDB
40#endif
41
42#ifdef unix
43# ifndef hpux
44#  include <unistd.h>
45#  include <sys/types.h>
46
47#  ifdef TIME_WITH_SYS_TIME
48#   include <time.h>
49#   ifdef HAVE_SYS_TIME_H
50#     include <sys/time.h>
51#   endif
52#  else
53#   ifdef HAVE_SYS_TIME_H
54#     include <sys/time.h>
55#   else
56#     include <time.h>
57#   endif
58#  endif
59#  ifdef HAVE_SYS_TIMES_H
60#   include <sys/times.h>
61#  endif
62
63#  define INTERACTIVE 0
64#  define STACK_TRACE 1
65#  ifdef CALL_GDB
66static void debug (int);
67static void debug_stop (char **);
68#  endif
69#  ifndef __OPTIMIZE__
70static void stack_trace (char **);
71static void stack_trace_sigchld (int);
72#  endif
73# endif /* !hpux */
74#endif  /* unix */
75
76/*---------------------------------------------------------------------*
77 * File scope Variables (Variables share by several functions in
78 *                       the same file )
79 *
80 *---------------------------------------------------------------------*/
81/* data */
82jmp_buf si_start_jmpbuf;
83int siRandomStart;
84short si_restart=0;
85BOOLEAN siCntrlc = FALSE;
86
87typedef void (*si_hdl_typ)(int);
88
89
90/*0 implementation*/
91/*---------------------------------------------------------------------*
92 * Functions declarations
93 *
94 *---------------------------------------------------------------------*/
95#ifndef MSDOS
96/* signals are not implemented in DJGCC */
97void sigint_handler(int sig);
98#endif /* MSDOS */
99
100si_hdl_typ si_set_signal ( int sig, si_hdl_typ signal_handler);
101
102/*---------------------------------------------------------------------*/
103/**
104 * @brief meta function for binding a signal to an handler
105
106 @param[in] sig             Signal number
107 @param[in] signal_handler  Pointer to signal handler
108
109 @return value of signal()
110**/
111/*---------------------------------------------------------------------*/
112si_hdl_typ si_set_signal (
113  int sig,
114  si_hdl_typ signal_handler
115  )
116{
117  si_hdl_typ retval=signal (sig, (si_hdl_typ)signal_handler);
118  if (retval == SIG_ERR)
119  {
120     fprintf(stderr, "Unable to init signal %d ... exiting...\n", sig);
121  }
122  siginterrupt(sig, 1);
123  return retval;
124}                               /* si_set_signal */
125
126
127/*---------------------------------------------------------------------*/
128/*-- linux and i386 ---*/
129#if defined(linux) && defined(__i386__)
130# if defined(HAVE_SIGCONTEXT) || defined(HAVE_ASM_SIGCONTEXT_H)
131#  include <asm/sigcontext.h>
132# else
133struct sigcontext_struct {
134        unsigned short gs, __gsh;
135        unsigned short fs, __fsh;
136        unsigned short es, __esh;
137        unsigned short ds, __dsh;
138        unsigned long edi;
139        unsigned long esi;
140        unsigned long ebp;
141        unsigned long esp;
142        unsigned long ebx;
143        unsigned long edx;
144        unsigned long ecx;
145        unsigned long eax;
146        unsigned long trapno;
147        unsigned long err;
148        unsigned long eip;
149        unsigned short cs, __csh;
150        unsigned long eflags;
151        unsigned long esp_at_signal;
152        unsigned short ss, __ssh;
153        unsigned long i387;
154        unsigned long oldmask;
155        unsigned long cr2;
156};
157# endif
158typedef struct sigcontext_struct sigcontext;
159
160
161/*2---------------------------------------------------------------------*/
162/**
163 * @brief signal handler for run time errors, linux/i386 version
164
165 @param[in] sig     
166 @param[in] s   
167**/
168/*---------------------------------------------------------------------*/
169void sigsegv_handler(int sig, sigcontext s)
170{
171  fprintf(stderr,"Singular : signal %d (v: %d/%u):\n",sig,SINGULAR_VERSION,feVersionId);
172  if (sig!=SIGINT)
173  {
174    fprintf(stderr,"Segment fault/Bus error occurred at %x because of %x (r:%d)\n"
175                   "please inform the authors\n",
176                   (int)s.eip,(int)s.cr2,siRandomStart);
177  }
178# ifdef __OPTIMIZE__
179  if(si_restart<3)
180  {
181    si_restart++;
182    fprintf(stderr,"trying to restart...\n");
183    init_signals();
184    longjmp(si_start_jmpbuf,1);
185  }
186# endif /* __OPTIMIZE__ */
187# ifdef CALL_GDB
188  if (sig!=SIGINT) debug(INTERACTIVE);
189# endif /* CALL_GDB */
190  exit(0);
191}
192
193/*---------------------------------------------------------------------*/
194/**
195 * @brief additional default signal handler
196
197  // some newer Linux version cannot have SIG_IGN for SIGCHLD,
198  // so use this nice routine here:
199  //  SuSe 9.x reports -1 always
200  //  Redhat 9.x/FC x reports sometimes -1
201  // see also: hpux_system
202
203 @param[in] sig     
204**/
205/*---------------------------------------------------------------------*/
206void sig_ign_hdl(int sig)
207{
208}
209
210# ifdef PAGE_TEST
211#  ifndef PAGE_INTERRUPT_TIME
212#   define PAGE_INTERRUPT_TIME 1
213#  endif
214
215/*---------------------------------------------------------------------*/
216/**
217 * @brief signal handler for segmentation faults
218
219 @param[in] sig     
220 @param[in] s   
221**/
222/*---------------------------------------------------------------------*/
223void sig11_handler(int sig, sigcontext s)
224{
225  unsigned long base =(unsigned long)(s.cr2&(~4095));
226  int i;
227  i=mmPage_tab_ind-1;
228  while (mmPage_tab[i]!=base) i--;
229  mmUse_tab[i]='1';
230  mmPage_tab_acc++;
231  mmPage_AllowAccess((void *)base);
232  si_set_signal(SIGSEGV,(si_hdl_typ)sig11_handler);
233}
234
235/*---------------------------------------------------------------------*/
236/**
237 * @brief signal handler for alarm signals
238
239 @param[in] sig     
240 @param[in] s   
241**/
242/*---------------------------------------------------------------------*/
243void sigalarm_handler(int sig, sigcontext s)
244{
245  int i=mmPage_tab_ind-1;
246  mmWriteStat();
247  for(;i>=0;i--)
248  {
249    mmPage_DenyAccess((void *)mmPage_tab[i]);
250  }
251  struct itimerval t,o;
252  memset(&t,0,sizeof(t));
253  t.it_value.tv_sec     =(unsigned)0;
254  t.it_value.tv_usec    =(unsigned) PAGE_INTERRUPT_TIME;
255  o.it_value.tv_sec     =(unsigned)0;
256  o.it_value.tv_usec    =(unsigned)PAGE_INTERRUPT_TIME;
257  setitimer(ITIMER_VIRTUAL,&t,&o);
258  si_set_signal(SIGVTALRM,(si_hdl_typ)sigalarm_handler);
259}
260# endif /* PAGE_TEST */
261
262/*2
263* init signal handlers, linux/i386 version
264*/
265void init_signals()
266{
267/*4 signal handler: linux*/
268# ifdef PAGE_TEST
269  si_set_signal(SIGSEGV,(si_hdl_typ)sig11_handler);
270  struct itimerval t,o;
271  memset(&t,0,sizeof(t));
272  t.it_value.tv_sec     =(unsigned)0;
273  t.it_value.tv_usec    =(unsigned)PAGE_INTERRUPT_TIME;
274  o.it_value.tv_sec     =(unsigned)0;
275  o.it_value.tv_usec    =(unsigned)PAGE_INTERRUPT_TIME;
276  setitimer(ITIMER_VIRTUAL,&t,&o);
277  si_set_signal(SIGVTALRM,(si_hdl_typ)sigalarm_handler);
278# else /* PAGE_TEST */
279  if (SIG_ERR==si_set_signal(SIGSEGV,(si_hdl_typ)sigsegv_handler))
280  {
281    PrintS("cannot set signal handler for SEGV\n");
282  }
283# endif /* PAGE_TEST */
284  if (SIG_ERR==si_set_signal(SIGFPE, (si_hdl_typ)sigsegv_handler))
285  {
286    PrintS("cannot set signal handler for FPE\n");
287  }
288  if (SIG_ERR==si_set_signal(SIGILL, (si_hdl_typ)sigsegv_handler))
289  {
290    PrintS("cannot set signal handler for ILL\n");
291  }
292  if (SIG_ERR==si_set_signal(SIGIOT, (si_hdl_typ)sigsegv_handler))
293  {
294    PrintS("cannot set signal handler for IOT\n");
295  }
296  if (SIG_ERR==si_set_signal(SIGINT ,(si_hdl_typ)sigint_handler))
297  {
298    PrintS("cannot set signal handler for INT\n");
299  }
300  //si_set_signal(SIGCHLD, (void (*)(int))SIG_IGN);
301  si_set_signal(SIGCHLD, (si_hdl_typ)sig_ign_hdl);
302}
303
304#else /* linux && __i386__ */
305/*---------------------------------------------------------------------*/
306/*-- SPARC_SUNOS_4 ---*/
307# ifdef SPARC_SUNOS_4
308/*2
309* signal handler for run time errors, sparc sunos 4 version
310*/
311void sigsegv_handler(int sig, int code, struct sigcontext *scp, char *addr)
312{
313  fprintf(stderr,"Singular : signal %d, code %d (v: %d/%u):\n",
314    sig,code,SINGULAR_VERSION,feVersionId);
315  if ((sig!=SIGINT)&&(sig!=SIGABRT))
316  {
317    fprintf(stderr,"Segment fault/Bus error occurred at %x (r:%d)\n"
318                   "please inform the authors\n",
319                   (int)addr,siRandomStart);
320  }
321#  ifdef __OPTIMIZE__
322  if(si_restart<3)
323  {
324    si_restart++;
325    fprintf(stderr,"trying to restart...\n");
326    init_signals();
327    longjmp(si_start_jmpbuf,1);
328  }
329#  endif /* __OPTIMIZE__ */
330#  ifdef CALL_GDB
331  if (sig!=SIGINT) debug(STACK_TRACE);
332#  endif /* CALL_GDB */
333  exit(0);
334}
335
336/*2
337* init signal handlers, sparc sunos 4 version
338*/
339void init_signals()
340{
341/*4 signal handler:*/
342  si_set_signal(SIGSEGV,sigsegv_handler);
343  si_set_signal(SIGBUS, sigsegv_handler);
344  si_set_signal(SIGFPE, sigsegv_handler);
345  si_set_signal(SIGILL, sigsegv_handler);
346  si_set_signal(SIGIOT, sigsegv_handler);
347  si_set_signal(SIGINT ,sigint_handler);
348  si_set_signal(SIGCHLD, (void (*)(int))SIG_IGN);
349}
350# else /* SPARC_SUNOS_4 */
351
352/*---------------------------------------------------------------------*/
353/*2
354* signal handler for run time errors, general version
355*/
356void sigsegv_handler(int sig)
357{
358  fprintf(stderr,"Singular : signal %d (v: %d/%u):\n",
359    sig,SINGULAR_VERSION,feVersionId);
360  if (sig!=SIGINT)
361  {
362    fprintf(stderr,"Segment fault/Bus error occurred (r:%d)\n"
363                   "please inform the authors\n",
364                   siRandomStart);
365  }
366#   ifdef __OPTIMIZE__
367  if(si_restart<3)
368  {
369    si_restart++;
370    fprintf(stderr,"trying to restart...\n");
371    init_signals();
372    longjmp(si_start_jmpbuf,1);
373  }
374#   endif /* __OPTIMIZE__ */
375#   ifdef unix
376#    ifndef hpux
377/* debug(..) does not work under HPUX (because ptrace does not work..) */
378#     ifdef CALL_GDB
379#      ifndef MSDOS
380  if (sig!=SIGINT) debug(STACK_TRACE);
381#      endif /* MSDOS */
382#     endif /* CALL_GDB */
383#    endif /* !hpux */
384#   endif /* unix */
385  exit(0);
386}
387
388/*2
389* init signal handlers, general version
390*/
391void init_signals()
392{
393#  ifndef MSDOS
394/* signals are not implemented in DJGCC */
395/*4 signal handler:*/
396  si_set_signal(SIGSEGV,(void (*) (int))sigsegv_handler);
397#    ifdef SIGBUS
398  si_set_signal(SIGBUS, sigsegv_handler);
399#    endif /* SIGBUS */
400#    ifdef SIGFPE
401  si_set_signal(SIGFPE, sigsegv_handler);
402#    endif /* SIGFPE */
403#    ifdef SIGILL
404  si_set_signal(SIGILL, sigsegv_handler);
405#    endif /* SIGILL */
406#    ifdef SIGIOT
407  si_set_signal(SIGIOT, sigsegv_handler);
408#    endif /* SIGIOT */
409#    ifdef SIGXCPU
410  si_set_signal(SIGXCPU, (void (*)(int))SIG_IGN);
411#    endif /* SIGIOT */
412  si_set_signal(SIGINT ,sigint_handler);
413  si_set_signal(SIGCHLD, (void (*)(int))SIG_IGN);
414#  endif /* !MSDOS */
415}
416# endif /* SPARC_SUNOS_4 */
417#endif /* linux && __i386__ */
418
419
420#ifndef MSDOS
421/*2
422* signal handler for SIGINT
423*/
424void sigint_handler(int sig)
425{
426  mflush();
427#  ifdef HAVE_FEREAD
428  if (fe_is_raw_tty) fe_temp_reset();
429#  endif /* HAVE_FEREAD */
430  loop
431  {
432    int cnt=0;
433    int c;
434    fprintf(stderr,"// ** Interrupt at cmd:`%s` in line:'%s'\n",
435      Tok2Cmdname(iiOp),my_yylinebuf);
436    if (feGetOptValue(FE_OPT_EMACS) == NULL)
437    {
438      fputs("abort command(a), continue(c) or quit Singular(q) ?",stderr);fflush(stderr);
439      c = fgetc(stdin);
440    }
441    else
442    {
443      c = 'a';
444    }
445   
446    switch(c)
447    {
448#  if defined(MONOM_COUNT) || defined(DIV_COUNT)
449              case 'e':
450#   ifdef MONOM_COUNT
451                extern void ResetMonomCount();
452                ResetMonomCount();
453#   endif /* MONOM_COUNT */
454#   ifdef DIV_COUNT
455                extern void ResetDivCount();
456                ResetDivCount();
457#   endif /* DIV_COUNT */
458                break;
459              case 'o':
460#   ifdef MONOM_COUNT
461                extern void OutputMonomCount();
462                OutputMonomCount();
463#   endif /* COUNT */
464#   ifdef DIV_COUNT
465                extern void OutputDivCount();
466                OutputDivCount();
467#   endif /* DIV_COUNT */
468                break;
469#  endif /* defined(MONOM_COUNT) || defined(DIV_COUNT) */
470      case 'q':
471                m2_end(2);
472      case 'r':
473                longjmp(si_start_jmpbuf,1);
474      case 'b':
475                VoiceBackTrack();
476                break;
477      case 'a':
478                siCntrlc++;
479      case 'c':
480                if (feGetOptValue(FE_OPT_EMACS) == NULL) fgetc(stdin);
481                si_set_signal(SIGINT ,(si_hdl_typ)sigint_handler);
482                return;
483                //siCntrlc ++;
484                //if (siCntrlc>2) si_set_signal(SIGINT,(si_hdl_typ) sigsegv_handler);
485                //else            si_set_signal(SIGINT,(si_hdl_typ) sigint_handler);
486    }
487    cnt++;
488    if(cnt>5) m2_end(2);
489  }
490}
491#endif /* !MSDOS */
492
493//#ifdef macintosh
494//#include <Types.h>
495//#include <Events.h>
496//#include <OSEvents.h>
497//#include <CursorCtl.h>
498//
499///*3
500//* macintosh only:
501//* side effect of ^C is to insert EOF at the end of the current
502//* input selection. We must drain input, reach this EOF, then clear it
503//*/
504//static void flush_intr(void)
505//{
506//  int c;
507//
508//  while ((c=getchar())!=EOF);
509//  clearerr(stdin);
510//}
511//
512///*3
513//* macintosh only:
514//* spin beach ball in MPW, allows MPW-tool to go to the background
515//* so you can use the finder and interrupts
516//*/
517//static void beachball(void)
518//{
519//  Show_Cursor(HIDDEN_CURSOR);
520//  SpinCursor(10);
521//}
522//#endif
523
524#ifndef MSDOS
525//void test_int()
526//{
527//#ifndef macintosh
528//  if (siCntrlc!=0)
529//  {
530//    int saveecho = si_echo;
531//    siCntrlc = FALSE;
532//    si_set_signal(SIGINT ,sigint_handler);
533////#ifdef macintosh
534////    flush_intr();
535////#endif
536//    iiDebug();
537//    si_echo = saveecho;
538//  }
539//#endif
540//}
541#endif /* !MSDOS */
542
543#ifdef unix
544# ifndef hpux
545#  ifndef __OPTIMIZE__
546#   ifndef MSDOS
547int si_stop_stack_trace_x;
548#    ifdef CALL_GDB
549static void debug (int method)
550{
551  if (feOptValue(FE_OPT_NO_TTY))
552  {
553    dReportError("Caught Signal 11");
554    return;
555  }
556  int pid;
557  char buf[16];
558  char *args[4] = { "gdb", "Singularg", NULL, NULL };
559
560#     ifdef HAVE_FEREAD
561  if (fe_is_raw_tty) fe_temp_reset();
562#     endif /* HAVE_FEREAD */
563
564  sprintf (buf, "%d", getpid ());
565
566  args[2] = buf;
567
568  pid = fork ();
569  if (pid == 0)
570  {
571    switch (method)
572    {
573      case INTERACTIVE:
574        fprintf (stderr, "debug_stop\n");
575        debug_stop (args);
576        break;
577      case STACK_TRACE:
578        fprintf (stderr, "stack_trace\n");
579        stack_trace (args);
580        break;
581      default:
582        // should not be reached:
583        exit(1);
584    }
585  }
586  else if (pid == -1)
587  {
588    perror ("could not fork");
589    return;
590  }
591
592  si_stop_stack_trace_x = 1;
593  while (si_stop_stack_trace_x) ;
594}
595
596static void debug_stop ( char **args)
597{
598  execvp (args[0], args);
599  perror ("exec failed");
600  _exit (0);
601}
602#    endif /* CALL_GDB */
603
604static int stack_trace_done;
605
606static void stack_trace (char **args)
607{
608  int pid;
609  int in_fd[2];
610  int out_fd[2];
611  fd_set fdset;
612  fd_set readset;
613  struct timeval tv;
614  int sel, index, state;
615  char buffer[256];
616  char c;
617
618  stack_trace_done = 0;
619
620  signal (SIGCHLD, stack_trace_sigchld);
621
622  if ((pipe (in_fd) == -1) || (pipe (out_fd) == -1))
623  {
624    perror ("could open pipe");
625    m2_end(999);
626  }
627
628  pid = fork ();
629  if (pid == 0)
630  {
631    close (0); dup2 (in_fd[0],0);   /* set the stdin to the in pipe */
632    close (1); dup2 (out_fd[1],1);  /* set the stdout to the out pipe */
633    close (2); dup2 (out_fd[1],2);  /* set the stderr to the out pipe */
634
635    execvp (args[0], args);      /* exec gdb */
636    perror ("exec failed");
637    m2_end(999);
638  }
639  else if (pid == -1)
640  {
641    perror ("could not fork");
642    m2_end(999);
643  }
644
645  FD_ZERO (&fdset);
646  FD_SET (out_fd[0], &fdset);
647
648  write (in_fd[1], "backtrace\n", 10);
649  write (in_fd[1], "p si_stop_stack_trace_x = 0\n", 28);
650  write (in_fd[1], "quit\n", 5);
651
652  index = 0;
653  state = 0;
654
655  loop
656  {
657    readset = fdset;
658    tv.tv_sec = 1;
659    tv.tv_usec = 0;
660
661#    ifdef hpux
662    sel = select (FD_SETSIZE, (int *)readset.fds_bits, NULL, NULL, &tv);
663#    else /* hpux */
664    sel = select (FD_SETSIZE, &readset, NULL, NULL, &tv);
665#    endif /* hpux */
666    if (sel == -1)
667      break;
668
669    if ((sel > 0) && (FD_ISSET (out_fd[0], &readset)))
670    {
671      if (read (out_fd[0], &c, 1))
672      {
673        switch (state)
674        {
675          case 0:
676            if (c == '#')
677            {
678              state = 1;
679              index = 0;
680              buffer[index++] = c;
681            }
682            break;
683          case 1:
684            buffer[index++] = c;
685            if ((c == '\n') || (c == '\r'))
686            {
687              buffer[index] = 0;
688              fprintf (stderr, "%s", buffer);
689              state = 0;
690              index = 0;
691            }
692            break;
693          default:
694            break;
695        }
696      }
697    }
698    else if (stack_trace_done)
699      break;
700  }
701
702  close (in_fd[0]);
703  close (in_fd[1]);
704  close (out_fd[0]);
705  close (out_fd[1]);
706  m2_end(0);
707}
708
709static void stack_trace_sigchld (int signum)
710{
711  stack_trace_done = 1;
712}
713
714#   endif /* !MSDOS */
715#  endif /* !__OPTIMIZE__ */
716# endif /* !hpux */
717#endif /* unix */
718
719/* Under HPUX 9, system(...) returns -1 if SIGCHLD does not equal
720   SIG_DFL. However, if it stays at SIG_DFL we get zombie processes
721   for terminated childs generated by fork. Therefors some special treatment
722   is necessary */
723#ifdef HPUX_9
724# undef system
725extern "C" {
726  int  hpux9_system(const char* call)
727  {
728    int ret;
729    si_set_signal(SIGCHLD, (void (*)(int))SIG_DFL);
730    ret = system(call);
731    si_set_signal(SIGCHLD, (void (*)(int))SIG_IGN);
732    return ret;
733  }
734}
735#endif /* HPUX_9 */
Note: See TracBrowser for help on using the repository browser.