source: git/Singular/cntrlc.cc @ 0fa9018

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