source: git/Singular/cntrlc.cc @ d7e6e0

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