source: git/Singular/cntrlc.cc @ ebc73ed

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