My Project
Loading...
Searching...
No Matches
cntrlc.cc
Go to the documentation of this file.
1/****************************************
2* Computer Algebra System SINGULAR *
3****************************************/
4/*
5* ABSTRACT - interupt handling
6*/
7
8#ifndef _GNU_SOURCE
9#define _GNU_SOURCE
10#endif
11
12#include "kernel/mod2.h"
13
14#include "reporter/si_signals.h"
15#include "Singular/fevoices.h"
16
17#include "misc/options.h"
18#include "Singular/tok.h"
19#include "Singular/ipshell.h"
20#include "Singular/cntrlc.h"
21#include "Singular/feOpt.h"
22#include "Singular/misc_ip.h"
25
26/* undef, if you don't want GDB to come up on error */
27
28#define CALL_GDB
29
30#if defined(__OPTIMIZE__) && defined(CALL_GDB)
31#undef CALL_GDB
32#endif
33
34 #ifdef TIME_WITH_SYS_TIME
35 #include <time.h>
36 #ifdef HAVE_SYS_TIME_H
37 #include <sys/time.h>
38 #endif
39 #else
40 #ifdef HAVE_SYS_TIME_H
41 #include <sys/time.h>
42 #else
43 #include <time.h>
44 #endif
45 #endif
46 #ifdef HAVE_SYS_TIMES_H
47 #include <sys/times.h>
48 #endif
49
50 #define INTERACTIVE 0
51 #define STACK_TRACE 1
52
53 #ifdef CALL_GDB
54 static void debug (int);
55 static void debug_stop (char *const*args);
56 #endif
57 #ifndef __OPTIMIZE__
58 static void stack_trace (char *const*args);
59 #endif
60
63
64void sig_pipe_hdl(int /*sig*/)
65{
66 if (pipeLastLink!=NULL)
67 {
70 WerrorS("pipe failed");
71 }
72}
73
75VAR volatile int defer_shutdown = 0;
76
77void sig_term_hdl(int /*sig*/)
78{
80 if (!defer_shutdown)
81 {
82 m2_end(1);
83 }
84}
85
86/*---------------------------------------------------------------------*
87 * File scope Variables (Variables shared by several functions in
88 * the same file )
89 *
90 *---------------------------------------------------------------------*/
91/* data */
95
96typedef void (*si_hdl_typ)(int);
97
98
99/*0 implementation*/
100/*---------------------------------------------------------------------*
101 * Functions declarations
102 *
103 *---------------------------------------------------------------------*/
104void sigint_handler(int /*sig*/);
105
106si_hdl_typ si_set_signal ( int sig, si_hdl_typ signal_handler);
107
108/*---------------------------------------------------------------------*/
109/**
110 * @brief meta function for binding a signal to an handler
111
112 @param[in] sig Signal number
113 @param[in] signal_handler Pointer to signal handler
114
115 @return value of signal()
116**/
117/*---------------------------------------------------------------------*/
118si_hdl_typ si_set_signal ( int sig, si_hdl_typ signal_handler)
119{
120#if 0
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 si_siginterrupt(sig, 0);
127 /*system calls will be restarted if interrupted by the specified
128 * signal sig. This is the default behavior in Linux.
129 */
130#else
131 struct sigaction new_action,old_action;
132 memset(&new_action, 0, sizeof(struct sigaction));
133
134 /* Set up the structure to specify the new action. */
135 new_action.sa_handler = signal_handler;
136 if (sig==SIGINT)
137 sigemptyset (&new_action.sa_mask);
138 else
139 new_action.sa_flags = SA_RESTART;
140
141 int r=si_sigaction (sig, &new_action, &old_action);
142 si_hdl_typ retval=(si_hdl_typ)old_action.sa_handler;
143 if (r == -1)
144 {
145 fprintf(stderr, "Unable to init signal %d ... exiting...\n", sig);
146 retval=SIG_ERR;
147 }
148#endif
149 return retval;
150} /* si_set_signal */
151
152
153/*---------------------------------------------------------------------*/
154#if defined(__linux__) && (defined(__i386) || defined(__amd64))
155/*2---------------------------------------------------------------------*/
156/**
157 * @brief signal handler for run time errors, linux/i386, x86_64 version
158
159 @param[in] sig
160 @param[in] s
161**/
162/*---------------------------------------------------------------------*/
163void sigsegv_handler(int sig, sigcontext s)
164{
165 fprintf(stderr,"Singular : signal %d (v: %d):\n",sig,SINGULAR_VERSION);
166 if (sig!=SIGINT)
167 {
168 fprintf(stderr,"current line:>>%s<<\n",my_yylinebuf);
169 fprintf(stderr,"Segment fault/Bus error occurred at %lx because of %lx (r:%d)\n"
170 "please inform the authors\n",
171 #ifdef __i386__
172 (long)s.eip,
173 #else /* x86_64*/
174 (long)s.rip,
175 #endif
176 (long)s.cr2,siRandomStart);
177 }
178#ifdef __OPTIMIZE__
179 if(si_restart<3)
180 {
181 si_restart++;
182 fputs("trying to restart...\n",stderr);
183 init_signals();
184 longjmp(si_start_jmpbuf,1);
185 }
186#endif /* __OPTIMIZE__ */
187#ifdef CALL_GDB
188 if (sig!=SIGINT)
189 {
191 else debug(INTERACTIVE);
192 }
193#endif /* CALL_GDB */
194 exit(0);
195}
196
197/*---------------------------------------------------------------------*/
198#elif defined(SunOS) /*SPARC_SUNOS*/
199/*2
200* signal handler for run time errors, sparc sunos 4 version
201*/
202void sigsegv_handler(int sig, int code, struct sigcontext *scp, char *addr)
203{
204 fprintf(stderr,"Singular : signal %d, code %d (v: %d):\n",
205 sig,code,SINGULAR_VERSION);
206 if ((sig!=SIGINT)&&(sig!=SIGABRT))
207 {
208 fprintf(stderr,"current line:>>%s<<\n",my_yylinebuf);
209 fprintf(stderr,"Segment fault/Bus error occurred at %x (r:%d)\n"
210 "please inform the authors\n",
211 (int)addr,siRandomStart);
212 }
213#ifdef __OPTIMIZE__
214 if(si_restart<3)
215 {
216 si_restart++;
217 fputs("trying to restart...\n",stderr);
218 init_signals();
219 longjmp(si_start_jmpbuf,1);
220 }
221#endif /* __OPTIMIZE__ */
222#ifdef CALL_GDB
223 if (sig!=SIGINT) debug(STACK_TRACE);
224#endif /* CALL_GDB */
225 exit(0);
226}
227
228#else
229
230/*---------------------------------------------------------------------*/
231/*2
232* signal handler for run time errors, general version
233*/
234void sigsegv_handler(int sig)
235{
236 fprintf(stderr,"Singular : signal %d (v: %d):\n",
237 sig,SINGULAR_VERSION);
238 if (sig!=SIGINT)
239 {
240 fprintf(stderr,"current line:>>%s<<\n",my_yylinebuf);
241 fprintf(stderr,"Segment fault/Bus error occurred (r:%d)\n"
242 "please inform the authors\n",
244 }
245 #ifdef __OPTIMIZE__
246 if(si_restart<3)
247 {
248 si_restart++;
249 fputs("trying to restart...\n",stderr);
250 init_signals();
251 longjmp(si_start_jmpbuf,1);
252 }
253 #endif /* __OPTIMIZE__ */
254 #ifdef CALL_GDB
255 if (sig!=SIGINT) debug(STACK_TRACE);
256 #endif /* CALL_GDB */
257 exit(0);
258}
259#endif
260
261
262/*2
263* signal handler for SIGINT
264*/
266void sigint_handler(int /*sig*/)
267{
268 mflush();
269 #ifdef HAVE_FEREAD
271 #endif /* HAVE_FEREAD */
272 char default_opt=' ';
273 if ((feOptSpec[FE_OPT_CNTRLC].value!=NULL)
274 && ((char*)(feOptSpec[FE_OPT_CNTRLC].value))[0])
275 { default_opt=((char*)(feOptSpec[FE_OPT_CNTRLC].value))[0]; }
276 loop
277 {
278 int cnt=0;
279 int c;
280
282 {
283 c = 'q';
284 }
285 else if (default_opt!=' ')
286 {
287 c = default_opt;
288 }
289 else
290 {
291 fprintf(stderr,"// ** Interrupt at cmd:`%s` in line:'%s'\n",
293 if (feOptValue(FE_OPT_EMACS) == NULL)
294 {
295 fputs("abort after this command(a), abort immediately(r), print backtrace(b), continue(c) or quit Singular(q) ?",stderr);
296 fflush(stderr);fflush(stdin);
297 c = fgetc(stdin);
298 }
299 else
300 {
301 c = 'a';
302 }
303 }
304
305 switch(c)
306 {
307 case 'q': case EOF:
308 m2_end(2);
309 case 'r':
310 if (sigint_handler_cnt<3)
311 {
313 fputs("** Warning: Singular should be restarted as soon as possible **\n",stderr);
314 fflush(stderr);
315 extern void my_yy_flush();
316 my_yy_flush();
318 longjmp(si_start_jmpbuf,1);
319 }
320 else
321 {
322 fputs("** tried too often, try another possibility **\n",stderr);
323 fflush(stderr);
324 }
325 break;
326 case 'b':
328 break;
329 case 'a':
330 siCntrlc++;
331 case 'c':
332 if ((feOptValue(FE_OPT_EMACS) == NULL) && (default_opt!=' '))
333 {
334 /* Read until a newline or EOF */
335 while (c != EOF && c != '\n') c = fgetc(stdin);
336 }
338 return;
339 //siCntrlc ++;
340 //if (siCntrlc>2) si_set_signal(SIGINT,(si_hdl_typ) sigsegv_handler);
341 //else si_set_signal(SIGINT,(si_hdl_typ) sigint_handler);
342 }
343 cnt++;
344 if(cnt>5) m2_end(2);
345 }
346}
347
348//void test_int()
349//{
350// if (siCntrlc!=0)
351// {
352// int saveecho = si_echo;
353// siCntrlc = FALSE;
354// si_set_signal(SIGINT ,sigint_handler);
355// iiDebug();
356// si_echo = saveecho;
357// }
358//}
359
360# ifndef __OPTIMIZE__
362# ifdef CALL_GDB
363static void debug (int method)
364{
365 if (feOptValue(FE_OPT_NO_TTY))
366 {
367 dReportError("Caught Signal 11");
368 return;
369 }
370 /* REMARK FOR NEWER LINUX SYSTEMS:
371Attaching to a process on Linux with GDB as a normal user may fail with "ptrace:Operation not permitted". By default Linux does not allow attaching to a process which wasn't launched by the debugger (see the Yama security documentation for more details). (https://www.kernel.org/doc/Documentation/security/Yama.txt)
372
373There are ways to workaround this:
374
375 Run the following command as super user: echo 0| sudo tee /proc/sys/kernel/yama/ptrace_scope
376
377 This will set the ptrace level to 0, after this just with user permissions you can attach to processes which are not launched by the debugger.
378
379 On distributions without Yama (such as Raspbian) you can use libcap2-bin to assign ptrace permissions to specific executables: sudo setcap cap_sys_ptrace=eip /usr/bin/gdb
380*/
381 int pid;
382 char buf[16];
383 char * args[4] = { (char*)"gdb", (char*)"Singular", NULL, NULL };
384
385 #ifdef HAVE_FEREAD
387 #endif /* HAVE_FEREAD */
388
389 sprintf (buf, "%d", getpid ());
390
391 args[2] = buf;
392
393 pid = fork ();
394 if (pid == 0)
395 {
396 switch (method)
397 {
398 case INTERACTIVE:
399 fputs ("\n\nquit with \"p si_stop_stack_trace_x=0\"\n\n\n",stderr);
400 debug_stop (args);
401 break;
402 case STACK_TRACE:
403 fputs ("stack_trace\n",stderr);
404 stack_trace (args);
405 break;
406 default:
407 // should not be reached:
408 exit(1);
409 }
410 }
411 else if (pid == -1)
412 {
413 perror ("could not fork");
414 return;
415 }
416
418 while (si_stop_stack_trace_x) ;
419}
420
421static void debug_stop (char *const*args)
422{
423 execvp (args[0], args);
424 perror ("exec failed");
425 _exit (0);
426}
427# endif /* CALL_GDB */
428
429static void stack_trace (char *const*args)
430{
431 int pid;
432 int in_fd[2];
433 int out_fd[2];
434 fd_set fdset;
435 fd_set readset;
436 struct timeval tv;
437 int sel, index, state;
438 char buffer[256];
439 char c;
440
441 if ((pipe (in_fd) == -1) || (pipe (out_fd) == -1))
442 {
443 perror ("could open pipe");
444 m2_end(999);
445 }
446
447 pid = fork ();
448 if (pid == 0)
449 {
450 si_close (0); si_dup2 (in_fd[0],0); /* set the stdin to the in pipe */
451 si_close (1); si_dup2 (out_fd[1],1); /* set the stdout to the out pipe */
452 si_close (2); si_dup2 (out_fd[1],2); /* set the stderr to the out pipe */
453
454 execvp (args[0], args); /* exec gdb */
455 perror ("exec failed");
456 m2_end(999);
457 }
458 else if (pid == -1)
459 {
460 perror ("could not fork");
461 m2_end(999);
462 }
463
464 FD_ZERO (&fdset);
465 FD_SET (out_fd[0], &fdset);
466
467 si_write (in_fd[1], "backtrace\n", 10);
468 si_write (in_fd[1], "p si_stop_stack_trace_x = 0\n", 28);
469 si_write (in_fd[1], "quit\n", 5);
470
471 index = 0;
472 state = 0;
473
474 loop
475 {
476 readset = fdset;
477 tv.tv_sec = 1;
478 tv.tv_usec = 0;
479
480 sel = si_select (FD_SETSIZE, &readset, NULL, NULL, &tv);
481 if (sel == -1)
482 break;
483
484 if ((sel > 0) && (FD_ISSET (out_fd[0], &readset)))
485 {
486 if (si_read (out_fd[0], &c, 1))
487 {
488 switch (state)
489 {
490 case 0:
491 if (c == '#')
492 {
493 state = 1;
494 index = 0;
495 buffer[index++] = c;
496 }
497 break;
498 case 1:
499 buffer[index++] = c;
500 if ((c == '\n') || (c == '\r'))
501 {
502 buffer[index] = 0;
503 fputs (buffer,stderr);
504 state = 0;
505 index = 0;
506 }
507 break;
508 default:
509 break;
510 }
511 }
512 }
513 else if (si_stop_stack_trace_x==0)
514 break;
515 }
516
517 si_close (in_fd[0]);
518 si_close (in_fd[1]);
519 si_close (out_fd[0]);
520 si_close (out_fd[1]);
521 m2_end(0);
522}
523
524# endif /* !__OPTIMIZE__ */
525
526/// init signal handlers and error handling for libraries: NTL, factory
528{
529// signal handler -------------------------------------------------------
530 #ifdef SIGSEGV
532 #endif
533 #ifdef SIGBUS
535 #endif
536 #ifdef SIGFPE
538 #endif
539 #ifdef SIGILL
541 #endif
542 #ifdef SIGIOT
544 #endif
549}
550
int BOOLEAN
Definition: auxiliary.h:87
#define TRUE
Definition: auxiliary.h:100
#define FALSE
Definition: auxiliary.h:96
VAR si_link pipeLastLink
Definition: cntrlc.cc:61
void sig_pipe_hdl(int)
Definition: cntrlc.cc:64
VAR jmp_buf si_start_jmpbuf
Definition: cntrlc.cc:92
static void stack_trace(char *const *args)
Definition: cntrlc.cc:429
VAR BOOLEAN singular_in_batchmode
Definition: cntrlc.cc:62
si_hdl_typ si_set_signal(int sig, si_hdl_typ signal_handler)
meta function for binding a signal to an handler
Definition: cntrlc.cc:118
VAR volatile int si_stop_stack_trace_x
Definition: cntrlc.cc:361
static void debug(int)
Definition: cntrlc.cc:363
VAR volatile BOOLEAN do_shutdown
Definition: cntrlc.cc:74
VAR short si_restart
Definition: cntrlc.cc:94
#define INTERACTIVE
Definition: cntrlc.cc:50
void sig_term_hdl(int)
Definition: cntrlc.cc:77
#define STACK_TRACE
Definition: cntrlc.cc:51
VAR volatile int defer_shutdown
Definition: cntrlc.cc:75
VAR int sigint_handler_cnt
Definition: cntrlc.cc:265
void sigint_handler(int)
Definition: cntrlc.cc:266
void(* si_hdl_typ)(int)
Definition: cntrlc.cc:96
void sigsegv_handler(int sig)
Definition: cntrlc.cc:234
VAR int siRandomStart
Definition: cntrlc.cc:93
static void debug_stop(char *const *args)
Definition: cntrlc.cc:421
void init_signals()
init signal handlers and error handling for libraries: NTL, factory
Definition: cntrlc.cc:527
const CanonicalForm int s
Definition: facAbsFact.cc:51
void WerrorS(const char *s)
Definition: feFopen.cc:24
static void * feOptValue(feOptIndex opt)
Definition: feOpt.h:40
EXTERN_VAR struct fe_option feOptSpec[]
Definition: feOpt.h:17
VAR char my_yylinebuf[80]
Definition: febase.cc:44
if(!FE_OPT_NO_SHELL_FLAG)(void) system(sys)
VAR BOOLEAN fe_is_raw_tty
Definition: fereadl.c:72
void fe_temp_reset(void)
Definition: fereadl.c:110
VAR Voice * currentVoice
Definition: fevoices.cc:49
void VoiceBackTrack()
Definition: fevoices.cc:77
Voice * feInitStdin(Voice *pp)
Definition: fevoices.cc:677
const char * Tok2Cmdname(int tok)
Definition: gentable.cc:140
#define VAR
Definition: globaldefs.h:5
VAR int iiOp
Definition: iparith.cc:222
This file provides miscellaneous functionality.
#define SINGULAR_VERSION
Definition: mod2.h:87
int dReportError(const char *fmt,...)
Definition: dError.cc:44
void m2_end(int i)
Definition: misc_ip.cc:1097
#define NULL
Definition: omList.c:12
VAR BOOLEAN siCntrlc
Definition: options.c:14
static int index(p_Length length, p_Ord ord)
Definition: p_Procs_Impl.h:592
#define mflush()
Definition: reporter.h:58
void my_yy_flush()
Definition: scanner.cc:2318
int status int void * buf
Definition: si_signals.h:59
#define si_siginterrupt(arg1, arg2)
#define loop
Definition: structs.h:75