source: git/Singular/cntrlc.cc @ e5fc4d4

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