source: git/Singular/cntrlc.cc @ 16f511

spielwiese
Last change on this file since 16f511 was 16f511, checked in by Oleksandr Motsak <motsak@…>, 11 years ago
Fixed the usage of "config.h" (if defined HAVE_CONFIG_H)
  • Property mode set to 100644
File size: 14.2 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#ifdef HAVE_CONFIG_H
22#include "config.h"
23#endif /* HAVE_CONFIG_H */
24#include <kernel/mod2.h>
25#include <omalloc/omalloc.h>
26
27#include <kernel/polys.h>
28#include <kernel/febase.h>
29void sig_chld_hdl(int sig); /*#include <Singular/links/ssiLink.h>*/
30//#include <Singular/feOpt.h>
31//#include <Singular/version.h>
32//#include <Singular/silink.h>
33//#include <Singular/ssiLink.h>
34#include <Singular/si_signals.h>
35
36#include "tok.h"
37#include "ipshell.h"
38#include "cntrlc.h"
39#include "feOpt.h"
40#include "version.h"
41#include "links/silink.h"
42
43/* undef, if you don't want GDB to come up on error */
44
45#if defined(__OPTIMIZE__) && defined(CALL_GDB)
46#undef CALL_GDB
47#endif
48
49#if defined(unix)
50 #include <unistd.h>
51 #include <sys/types.h>
52
53 #ifdef TIME_WITH_SYS_TIME
54   #include <time.h>
55   #ifdef HAVE_SYS_TIME_H
56     #include <sys/time.h>
57   #endif
58 #else
59   #ifdef HAVE_SYS_TIME_H
60     #include <sys/time.h>
61   #else
62     #include <time.h>
63   #endif
64 #endif
65 #ifdef HAVE_SYS_TIMES_H
66   #include <sys/times.h>
67 #endif
68
69 #define INTERACTIVE 0
70 #define STACK_TRACE 1
71
72 #ifdef CALL_GDB
73   static void debug (int);
74   static void debug_stop (char *const*args);
75 #endif
76 #ifndef __OPTIMIZE__
77   static void stack_trace_sigchld (int);
78   static void stack_trace (char *const*args);
79 #endif
80#endif
81
82si_link pipeLastLink=NULL;
83BOOLEAN singular_in_batchmode=FALSE;
84
85void sig_pipe_hdl(int /*sig*/)
86{
87 if (pipeLastLink!=NULL)
88 {
89   slClose(pipeLastLink);
90   pipeLastLink=NULL;
91   WerrorS("pipe failed");
92 }
93}
94
95void sig_term_hdl(int /*sig*/)
96{
97 while (ssiToBeClosed!=NULL)
98 {
99   slClose(ssiToBeClosed->l);
100   if (ssiToBeClosed==NULL) break;
101   ssiToBeClosed=(link_list)ssiToBeClosed->next;
102 }
103 exit(1);
104}
105
106/*---------------------------------------------------------------------*
107 * File scope Variables (Variables share by several functions in
108 *                       the same file )
109 *
110 *---------------------------------------------------------------------*/
111/* data */
112jmp_buf si_start_jmpbuf;
113int siRandomStart;
114short si_restart=0;
115BOOLEAN siCntrlc = FALSE;
116
117typedef void (*si_hdl_typ)(int);
118
119
120/*0 implementation*/
121/*---------------------------------------------------------------------*
122 * Functions declarations
123 *
124 *---------------------------------------------------------------------*/
125void sigint_handler(int sig);
126
127si_hdl_typ si_set_signal ( int sig, si_hdl_typ signal_handler);
128
129/*---------------------------------------------------------------------*/
130/**
131 * @brief meta function for binding a signal to an handler
132
133 @param[in] sig             Signal number
134 @param[in] signal_handler  Pointer to signal handler
135
136 @return value of signal()
137**/
138/*---------------------------------------------------------------------*/
139si_hdl_typ si_set_signal ( int sig, si_hdl_typ signal_handler)
140{
141#if 0
142  si_hdl_typ retval=signal (sig, (si_hdl_typ)signal_handler);
143  if (retval == SIG_ERR)
144  {
145     fprintf(stderr, "Unable to init signal %d ... exiting...\n", sig);
146  }
147  si_siginterrupt(sig, 0);
148  /*system calls will be restarted if interrupted by  the  specified
149   * signal sig.  This is the default behavior in Linux.
150   */
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=si_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__
419volatile int 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, "\n\nquit with \"p si_stop_stack_trace_x=0\"\n\n\n");
447        debug_stop (args);
448        break;
449      case STACK_TRACE:
450        fprintf (stderr, "stack_trace\n");
451        stack_trace (args);
452        break;
453      default:
454        // should not be reached:
455        exit(1);
456    }
457  }
458  else if (pid == -1)
459  {
460    perror ("could not fork");
461    return;
462  }
463
464  si_stop_stack_trace_x = 1;
465  while (si_stop_stack_trace_x) ;
466}
467
468static void debug_stop (char *const*args)
469{
470  execvp (args[0], args);
471  perror ("exec failed");
472  _exit (0);
473}
474#    endif /* CALL_GDB */
475
476static void stack_trace (char *const*args)
477{
478  int pid;
479  int in_fd[2];
480  int out_fd[2];
481  fd_set fdset;
482  fd_set readset;
483  struct timeval tv;
484  int sel, index, state;
485  char buffer[256];
486  char c;
487
488  if ((pipe (in_fd) == -1) || (pipe (out_fd) == -1))
489  {
490    perror ("could open pipe");
491    m2_end(999);
492  }
493
494  pid = fork ();
495  if (pid == 0)
496  {
497    si_close (0); si_dup2 (in_fd[0],0);   /* set the stdin to the in pipe */
498    si_close (1); si_dup2 (out_fd[1],1);  /* set the stdout to the out pipe */
499    si_close (2); si_dup2 (out_fd[1],2);  /* set the stderr to the out pipe */
500
501    execvp (args[0], args);      /* exec gdb */
502    perror ("exec failed");
503    m2_end(999);
504  }
505  else if (pid == -1)
506  {
507    perror ("could not fork");
508    m2_end(999);
509  }
510
511  FD_ZERO (&fdset);
512  FD_SET (out_fd[0], &fdset);
513
514  si_write (in_fd[1], "backtrace\n", 10);
515  si_write (in_fd[1], "p si_stop_stack_trace_x = 0\n", 28);
516  si_write (in_fd[1], "quit\n", 5);
517
518  index = 0;
519  state = 0;
520
521  loop
522  {
523    readset = fdset;
524    tv.tv_sec = 1;
525    tv.tv_usec = 0;
526
527    sel = si_select (FD_SETSIZE, &readset, NULL, NULL, &tv);
528    if (sel == -1)
529      break;
530
531    if ((sel > 0) && (FD_ISSET (out_fd[0], &readset)))
532    {
533      if (si_read (out_fd[0], &c, 1))
534      {
535        switch (state)
536        {
537          case 0:
538            if (c == '#')
539            {
540              state = 1;
541              index = 0;
542              buffer[index++] = c;
543            }
544            break;
545          case 1:
546            buffer[index++] = c;
547            if ((c == '\n') || (c == '\r'))
548            {
549              buffer[index] = 0;
550              fprintf (stderr, "%s", buffer);
551              state = 0;
552              index = 0;
553            }
554            break;
555          default:
556            break;
557        }
558      }
559    }
560    else if (si_stop_stack_trace_x==0)
561      break;
562  }
563
564  si_close (in_fd[0]);
565  si_close (in_fd[1]);
566  si_close (out_fd[0]);
567  si_close (out_fd[1]);
568  m2_end(0);
569}
570
571#  endif /* !__OPTIMIZE__ */
572#endif /* unix */
573
574/*2
575* init signal handlers
576*/
577void init_signals()
578{
579  #ifdef SIGSEGV
580  si_set_signal(SIGSEGV,(si_hdl_typ)sigsegv_handler);
581  #endif
582  #ifdef SIGBUS
583  si_set_signal(SIGBUS, (si_hdl_typ)sigsegv_handler);
584  #endif
585  #ifdef SIGFPE
586  si_set_signal(SIGFPE, (si_hdl_typ)sigsegv_handler);
587  #endif
588  #ifdef SIGILL
589  si_set_signal(SIGILL, (si_hdl_typ)sigsegv_handler);
590  #endif
591  #ifdef SIGIOT
592  si_set_signal(SIGIOT, (si_hdl_typ)sigsegv_handler);
593  #endif
594  si_set_signal(SIGINT ,(si_hdl_typ)sigint_handler);
595  si_set_signal(SIGCHLD, (si_hdl_typ)sig_chld_hdl);
596  si_set_signal(SIGPIPE, (si_hdl_typ)sig_pipe_hdl);
597  si_set_signal(SIGTERM, (si_hdl_typ)sig_term_hdl);
598}
599
Note: See TracBrowser for help on using the repository browser.