source: git/Singular/cntrlc.cc @ f8565a

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