source: git/Singular/cntrlc.cc @ c232af

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