source: git/Singular/cntrlc.cc @ 8d73ea

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