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
86void sig_term_hdl_child(int /*sig*/)
87{
88 _exit(0);
89}
90
91
92/*---------------------------------------------------------------------*
93 * File scope Variables (Variables shared by several functions in
94 * the same file )
95 *
96 *---------------------------------------------------------------------*/
97/* data */
101
102/*0 implementation*/
103/*---------------------------------------------------------------------*
104 * Functions declarations
105 *
106 *---------------------------------------------------------------------*/
107void sigint_handler(int /*sig*/);
108
109si_hdl_typ si_set_signal ( int sig, si_hdl_typ signal_handler);
110
111/*---------------------------------------------------------------------*/
112/**
113 * @brief meta function for binding a signal to an handler
114
115 @param[in] sig Signal number
116 @param[in] signal_handler Pointer to signal handler
117
118 @return value of signal()
119**/
120/*---------------------------------------------------------------------*/
121si_hdl_typ si_set_signal ( int sig, si_hdl_typ signal_handler)
122{
123#if 0
124 si_hdl_typ retval=signal (sig, (si_hdl_typ)signal_handler);
125 if (retval == SIG_ERR)
126 {
127 fprintf(stderr, "Unable to init signal %d ... exiting...\n", sig);
128 }
129 si_siginterrupt(sig, 0);
130 /*system calls will be restarted if interrupted by the specified
131 * signal sig. This is the default behavior in Linux.
132 */
133#else
134 struct sigaction new_action,old_action;
135 memset(&new_action, 0, sizeof(struct sigaction));
136
137 /* Set up the structure to specify the new action. */
138 new_action.sa_handler = signal_handler;
139 if (sig==SIGINT)
140 sigemptyset (&new_action.sa_mask);
141 else
142 new_action.sa_flags = SA_RESTART /*| SA_NOCLDWAIT*/;
143
144 int r=si_sigaction (sig, &new_action, &old_action);
145 si_hdl_typ retval=(si_hdl_typ)old_action.sa_handler;
146 if (r == -1)
147 {
148 fprintf(stderr, "Unable to init signal %d ... exiting...\n", sig);
149 retval=SIG_ERR;
150 }
151#endif
152 return retval;
153} /* si_set_signal */
154
155
156/*---------------------------------------------------------------------*/
157#if defined(__linux__) && (defined(__i386) || defined(__amd64))
158/*2---------------------------------------------------------------------*/
159/**
160 * @brief signal handler for run time errors, linux/i386, x86_64 version
161
162 @param[in] sig
163 @param[in] s
164**/
165/*---------------------------------------------------------------------*/
166void sigsegv_handler(int sig, sigcontext s)
167{
168 fprintf(stderr,"Singular : signal %d (v: %d):\n",sig,SINGULAR_VERSION);
169 if (sig!=SIGINT)
170 {
171 fprintf(stderr,"current line:>>%s<<\n",my_yylinebuf);
172 fprintf(stderr,"Segment fault/Bus error occurred at %lx because of %lx (r:%d)\n"
173 "please inform the authors\n",
174 #ifdef __i386__
175 (long)s.eip,
176 #else /* x86_64*/
177 (long)s.rip,
178 #endif
179 (long)s.cr2,siRandomStart);
180 }
181#ifdef __OPTIMIZE__
182 if(si_restart<3)
183 {
184 si_restart++;
185 fputs("trying to restart...\n",stderr);
186 init_signals();
187 longjmp(si_start_jmpbuf,1);
188 }
189#endif /* __OPTIMIZE__ */
190#ifdef CALL_GDB
191 if (sig!=SIGINT)
192 {
194 else debug(INTERACTIVE);
195 }
196#endif /* CALL_GDB */
197 exit(0);
198}
199
200/*---------------------------------------------------------------------*/
201#elif defined(SunOS) /*SPARC_SUNOS*/
202/*2
203* signal handler for run time errors, sparc sunos 4 version
204*/
205void sigsegv_handler(int sig, int code, struct sigcontext *scp, char *addr)
206{
207 fprintf(stderr,"Singular : signal %d, code %d (v: %d):\n",
208 sig,code,SINGULAR_VERSION);
209 if ((sig!=SIGINT)&&(sig!=SIGABRT))
210 {
211 fprintf(stderr,"current line:>>%s<<\n",my_yylinebuf);
212 fprintf(stderr,"Segment fault/Bus error occurred at %x (r:%d)\n"
213 "please inform the authors\n",
214 (int)addr,siRandomStart);
215 }
216#ifdef __OPTIMIZE__
217 if(si_restart<3)
218 {
219 si_restart++;
220 fputs("trying to restart...\n",stderr);
221 init_signals();
222 longjmp(si_start_jmpbuf,1);
223 }
224#endif /* __OPTIMIZE__ */
225#ifdef CALL_GDB
226 if (sig!=SIGINT) debug(STACK_TRACE);
227#endif /* CALL_GDB */
228 exit(0);
229}
230
231#else
232
233/*---------------------------------------------------------------------*/
234/*2
235* signal handler for run time errors, general version
236*/
237void sigsegv_handler(int sig)
238{
239 fprintf(stderr,"Singular : signal %d (v: %d):\n",
240 sig,SINGULAR_VERSION);
241 if (sig!=SIGINT)
242 {
243 fprintf(stderr,"current line:>>%s<<\n",my_yylinebuf);
244 fprintf(stderr,"Segment fault/Bus error occurred (r:%d)\n"
245 "please inform the authors\n",
247 }
248 #ifdef __OPTIMIZE__
249 if(si_restart<3)
250 {
251 si_restart++;
252 fputs("trying to restart...\n",stderr);
253 init_signals();
254 longjmp(si_start_jmpbuf,1);
255 }
256 #endif /* __OPTIMIZE__ */
257 #ifdef CALL_GDB
258 if (sig!=SIGINT) debug(STACK_TRACE);
259 #endif /* CALL_GDB */
260 exit(0);
261}
262#endif
263
264
265/*2
266* signal handler for SIGINT
267*/
269void sigint_handler(int /*sig*/)
270{
271 mflush();
272 #ifdef HAVE_FEREAD
274 #endif /* HAVE_FEREAD */
275 char default_opt=' ';
276 if ((feOptSpec[FE_OPT_CNTRLC].value!=NULL)
277 && ((char*)(feOptSpec[FE_OPT_CNTRLC].value))[0])
278 { default_opt=((char*)(feOptSpec[FE_OPT_CNTRLC].value))[0]; }
279 loop
280 {
281 int cnt=0;
282 int c;
283
285 {
286 c = 'q';
287 }
288 else if (default_opt!=' ')
289 {
290 c = default_opt;
291 }
292 else
293 {
294 fprintf(stderr,"// ** Interrupt at cmd:`%s` in line:'%s'\n",
296 if (feOptValue(FE_OPT_EMACS) == NULL)
297 {
298 fputs("abort after this command(a), abort immediately(r), print backtrace(b), continue(c) or quit Singular(q) ?",stderr);
299 fflush(stderr);fflush(stdin);
300 c = fgetc(stdin);
301 }
302 else
303 {
304 c = 'a';
305 }
306 }
307
308 switch(c)
309 {
310 case 'q': case EOF:
311 m2_end(2);
312 case 'r':
313 if (sigint_handler_cnt<3)
314 {
316 fputs("** Warning: Singular should be restarted as soon as possible **\n",stderr);
317 fflush(stderr);
318 extern void my_yy_flush();
319 my_yy_flush();
321 longjmp(si_start_jmpbuf,1);
322 }
323 else
324 {
325 fputs("** tried too often, try another possibility **\n",stderr);
326 fflush(stderr);
327 }
328 break;
329 case 'b':
331 break;
332 case 'a':
333 siCntrlc++;
334 case 'c':
335 if ((feOptValue(FE_OPT_EMACS) == NULL) && (default_opt!=' '))
336 {
337 /* Read until a newline or EOF */
338 while (c != EOF && c != '\n') c = fgetc(stdin);
339 }
341 return;
342 //siCntrlc ++;
343 //if (siCntrlc>2) si_set_signal(SIGINT,(si_hdl_typ) sigsegv_handler);
344 //else si_set_signal(SIGINT,(si_hdl_typ) sigint_handler);
345 }
346 cnt++;
347 if(cnt>5) m2_end(2);
348 }
349}
350
351//void test_int()
352//{
353// if (siCntrlc!=0)
354// {
355// int saveecho = si_echo;
356// siCntrlc = FALSE;
357// si_set_signal(SIGINT ,sigint_handler);
358// iiDebug();
359// si_echo = saveecho;
360// }
361//}
362
363# ifndef __OPTIMIZE__
365# ifdef CALL_GDB
366static void debug (int method)
367{
368 if (feOptValue(FE_OPT_NO_TTY))
369 {
370 dReportError("Caught Signal 11");
371 return;
372 }
373 /* REMARK FOR NEWER LINUX SYSTEMS:
374Attaching 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)
375
376There are ways to workaround this:
377
378 Run the following command as super user: echo 0| sudo tee /proc/sys/kernel/yama/ptrace_scope
379
380 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.
381
382 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
383*/
384 int pid;
385 char buf[16];
386 char * args[4] = { (char*)"gdb", (char*)"Singular", NULL, NULL };
387
388 #ifdef HAVE_FEREAD
390 #endif /* HAVE_FEREAD */
391
392 snprintf (buf, 16, "%d", getpid ());
393
394 args[2] = buf;
395
396 pid = fork ();
397 if (pid == 0)
398 {
399 switch (method)
400 {
401 case INTERACTIVE:
402 fputs ("\n\nquit with \"p si_stop_stack_trace_x=0\"\n\n\n",stderr);
403 debug_stop (args);
404 break;
405 case STACK_TRACE:
406 fputs ("stack_trace\n",stderr);
407 stack_trace (args);
408 break;
409 default:
410 // should not be reached:
411 exit(1);
412 }
413 }
414 else if (pid == -1)
415 {
416 perror ("could not fork");
417 return;
418 }
419
421 while (si_stop_stack_trace_x) ;
422}
423
424static void debug_stop (char *const*args)
425{
426 execvp (args[0], args);
427 perror ("exec failed");
428 _exit (0);
429}
430# endif /* CALL_GDB */
431
432static void stack_trace (char *const*args)
433{
434 int pid;
435 int in_fd[2];
436 int out_fd[2];
437 fd_set fdset;
438 fd_set readset;
439 struct timeval tv;
440 int sel, index, state;
441 char buffer[256];
442 char c;
443
444 if ((pipe (in_fd) == -1) || (pipe (out_fd) == -1))
445 {
446 perror ("could open pipe");
447 m2_end(999);
448 }
449
450 pid = fork ();
451 if (pid == 0)
452 {
453 si_close (0); si_dup2 (in_fd[0],0); /* set the stdin to the in pipe */
454 si_close (1); si_dup2 (out_fd[1],1); /* set the stdout to the out pipe */
455 si_close (2); si_dup2 (out_fd[1],2); /* set the stderr to the out pipe */
456
457 execvp (args[0], args); /* exec gdb */
458 perror ("exec failed");
459 m2_end(999);
460 }
461 else if (pid == -1)
462 {
463 perror ("could not fork");
464 m2_end(999);
465 }
466
467 FD_ZERO (&fdset);
468 FD_SET (out_fd[0], &fdset);
469
470 si_write (in_fd[1], "backtrace\n", 10);
471 si_write (in_fd[1], "p si_stop_stack_trace_x = 0\n", 28);
472 si_write (in_fd[1], "quit\n", 5);
473
474 index = 0;
475 state = 0;
476
477 loop
478 {
479 readset = fdset;
480 tv.tv_sec = 1;
481 tv.tv_usec = 0;
482
483 sel = si_select (FD_SETSIZE, &readset, NULL, NULL, &tv);
484 if (sel == -1)
485 break;
486
487 if ((sel > 0) && (FD_ISSET (out_fd[0], &readset)))
488 {
489 if (si_read (out_fd[0], &c, 1))
490 {
491 switch (state)
492 {
493 case 0:
494 if (c == '#')
495 {
496 state = 1;
497 index = 0;
498 buffer[index++] = c;
499 }
500 break;
501 case 1:
502 buffer[index++] = c;
503 if ((c == '\n') || (c == '\r'))
504 {
505 buffer[index] = 0;
506 fputs (buffer,stderr);
507 state = 0;
508 index = 0;
509 }
510 break;
511 default:
512 break;
513 }
514 }
515 }
516 else if (si_stop_stack_trace_x==0)
517 break;
518 }
519
520 si_close (in_fd[0]);
521 si_close (in_fd[1]);
522 si_close (out_fd[0]);
523 si_close (out_fd[1]);
524 m2_end(0);
525}
526
527# endif /* !__OPTIMIZE__ */
528
529/// init signal handlers and error handling for libraries: NTL, factory
531{
532// signal handler -------------------------------------------------------
533 #ifdef SIGSEGV
535 #endif
536 #ifdef SIGBUS
538 #endif
539 #ifdef SIGFPE
541 #endif
542 #ifdef SIGILL
544 #endif
545 #ifdef SIGIOT
547 #endif
552}
553
554//VAR si_hdl_typ si_sigint_handler;
557//VAR si_hdl_typ si_sig_pipe_hdl;
559
561{
562 //si_sigint_handler=si_set_signal(SIGINT ,(si_hdl_typ)sigint_handler);
564 //si_sig_pipe_hdl=si_set_signal(SIGPIPE, (si_hdl_typ)sig_pipe_hdl);
566}
567
569{
570// signal handler -------------------------------------------------------
571 //si_set_signal(SIGINT ,si_sigint_handler);
573 //si_set_signal(SIGPIPE, si_sig_pipe_hdl);
575}
576
int BOOLEAN
Definition auxiliary.h:88
#define TRUE
Definition auxiliary.h:101
#define FALSE
Definition auxiliary.h:97
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:98
static void stack_trace(char *const *args)
Definition cntrlc.cc:432
void si_set_signals()
Definition cntrlc.cc:560
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:121
VAR si_hdl_typ si_sig_term_hdl
Definition cntrlc.cc:558
VAR volatile int si_stop_stack_trace_x
Definition cntrlc.cc:364
void sig_term_hdl_child(int)
Definition cntrlc.cc:86
VAR si_hdl_typ si_sig_chld_hdl
Definition cntrlc.cc:555
static void debug(int)
Definition cntrlc.cc:366
VAR volatile BOOLEAN do_shutdown
Definition cntrlc.cc:74
void si_reset_signals()
Definition cntrlc.cc:568
VAR short si_restart
Definition cntrlc.cc:100
#define INTERACTIVE
Definition cntrlc.cc:50
void sig_term_hdl(int)
Definition cntrlc.cc:77
#define STACK_TRACE
Definition cntrlc.cc:51
VAR si_hdl_typ old_sig_chld_hdl
Definition cntrlc.cc:556
VAR volatile int defer_shutdown
Definition cntrlc.cc:75
VAR int sigint_handler_cnt
Definition cntrlc.cc:268
void sigint_handler(int)
Definition cntrlc.cc:269
void sigsegv_handler(int sig)
Definition cntrlc.cc:237
VAR int siRandomStart
Definition cntrlc.cc:99
static void debug_stop(char *const *args)
Definition cntrlc.cc:424
void init_signals()
init signal handlers and error handling for libraries: NTL, factory
Definition cntrlc.cc:530
void(* si_hdl_typ)(int)
Definition cntrlc.h:30
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
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:137
#define VAR
Definition globaldefs.h:5
VAR int iiOp
Definition iparith.cc:218
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:1102
#define NULL
Definition omList.c:12
VAR BOOLEAN siCntrlc
Definition options.c:14
static int index(p_Length length, p_Ord ord)
#define mflush()
Definition reporter.h:58
void my_yy_flush()
Definition scanner.cc:2318
#define si_siginterrupt(arg1, arg2)
int status int void * buf
Definition si_signals.h:69
#define loop
Definition structs.h:71