source: git/Singular/cntrlc.cc @ a40080

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