source: git/Singular/cntrlc.cc @ 50cbdc

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