source: git/Singular/cntrlc.cc @ fa1f52

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