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
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/*---------------------------------------------------------------------*/
119{
120#if 0
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
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);
143 if (r == -1)
144 {
145 fprintf(stderr, "Unable to init signal %d ... exiting...\n", sig);
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",
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();
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",
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();
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();
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",
294 {
295 fputs("abort after this command(a), abort immediately(r), print backtrace(b), continue(c) or quit Singular(q) ?",stderr);
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();
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{
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 snprintf (buf, 16, "%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];
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
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
551//VAR si_hdl_typ si_sigint_handler;
553//VAR si_hdl_typ si_sig_pipe_hdl;
554//VAR si_hdl_typ si_sig_term_hdl;
555
557{
558 //si_sigint_handler=si_set_signal(SIGINT ,(si_hdl_typ)sigint_handler);
560 //si_sig_pipe_hdl=si_set_signal(SIGPIPE, (si_hdl_typ)sig_pipe_hdl);
561 //si_sig_term_hdl=si_set_signal(SIGTERM, (si_hdl_typ)sig_term_hdl);
562}
563
565{
566// signal handler -------------------------------------------------------
567 //si_set_signal(SIGINT ,si_sigint_handler);
569 //si_set_signal(SIGPIPE, si_sig_pipe_hdl);
570 //si_set_signal(SIGTERM, si_sig_term_hdl);
571}
572
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
void si_set_signals()
Definition cntrlc.cc:556
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
VAR si_hdl_typ si_sig_chld_hdl
Definition cntrlc.cc:552
static void debug(int)
Definition cntrlc.cc:363
VAR volatile BOOLEAN do_shutdown
Definition cntrlc.cc:74
void si_reset_signals()
Definition cntrlc.cc:564
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
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:75