How does GDB/ptrace trap singals like SIGINT? - c

When I was googling my gdb and sigwait issue, I found this kernel bug thread
GDB is not trapping SIGINT. Ctrl+C terminates program when should break gdb.
Quote:
gdb puts the debugged process in its own pgrp and sets the terminal to that pgrp.
When you hit C-c, the signal goes to the current pgrp, i.e. to the debugged process and not to gdb. When a signal is delivered, ptrace will intercept it and let gdb decide what to do before it actually reaches the debugged process.
However, your program uses sigwait and so the signal is never actually delivered. Instead, you dequeue it via sigwait without going through actual signal delivery. ptrace only reports a signal that is about to be delivered. When you use sigwait, technically the signal is blocked the whole time and never delivered as such.
This comment got me more curious about how signal and GDB actually works,
1) What is the difference between "signal delivered" and "signal queued"?
2) How does GDB trap signals while the signal is sent to the debugged process?
Thanks,

Related

Do threads continue executing when a signal arrives?

I'm writing a multi-threaded program in C, where the main() changes the behavior of some signals and then spawns more threads. The question is: do the other threads continue executing when a signal arrives, or do they pause and resume execution when the signal is handled?
Thanks
do the other threads continue executing when a signal arrives
On Linux they do because a signal is only ever delivered to one thread. Unless the signal is SIGSTOP, which stops all threads of a process. See man signal(7) and man pthreads(7) for more details (ignore LinuxThreads info related to old threads implementation).
Although POSIX does not require that, so these details are OS specific.

Re-propagate a Caught Signal in Linux

I am trying to use sigwait() for SIGSEGV and other signals and then do something (says writing the timestamp to a file). Then, I would like the program to behave as if the signal were never caught (e.g. a coredump is generated when SIGSEGV happens -- assuming the system is configured for coredump).
I read through couple manpages, and I don't see an obvious way to do so.
Any suggestion?
Thanks in advance!
You can register a signal handler that won't cause the program to crash. Once you receive the signal, you'll enter the signal handler, and after executing the signal handler (write to file you said), you'll reenter the program where you left off.
If you want a core dump, you can use the linux core(5) command and it will create a core dump in your signal handler without ending your process.
http://www.alexonlinux.com/signal-handling-in-linux#signal_masks
I believe you can not handle few signals the way you want to for example
SIGKILL
SIGSEGV
as manual itself states The signals SIGKILL and SIGSTOP cannot be caught or ignored
check below links
SIGNAL(7) and SIGNAL(2) These links should provide good enough details on signal handling in linux
You can however register a signal handler to handle few other signals
to list signals in operating system like linux you can use below command
kill -l
and as far as generating core dump is conserned its generated by operating system click here for more info
check the example code here

Which "fatal" signals should a user-level program catch?

First of all, I do know that there was a similar question here in the past.
But that question wasn't answered properly. Instead, it diverted into suggestion what to do to catch signals.
So just to clarify: I've done whatever needs to be done to handle signals.
I have an application that forks a daemon that monitors the main process through pipe.
If a main process crashes (e.g. segmentation fault), it has a signal handler that writes all the required info to pipe and aborts.
The goal is to have as much info as possible when something bad happens to the application, w/o messing with "normal" operation, such as SIGHUP, SIGUSR1, etc.
So my question is: which signals should I catch?
I mean signals that w/o me catching them would cause application to abort anyway.
So far I've come up with the following list:
SIGINT (^C, user-initiated, but still good to know)
SIGTERM (kill <pid> from shell or, AFAIK, can be result of OutOfMemory)
SIGSEGV
SIGILL
SIGFPE
SIGBUS
SIGQUIT
Does anybody know if I miss something? kill -l has lots of them... :)
I'm looking at my copy of advanced programming the unix environment (Stevens). According to the table in the section on signals, the following POSIX signals will by default terminate the process, if you don't catch them. It wouldn't be unreasonable to monitor all of these that you don't use:
SIGABRT
SIGALRM
SIGFPE
SIGHUP
SIGILL
SIGINT
SIGKILL
SIGPIPE
SIGQUIT
SIGSEGV
SIGTERM
SIGUSR1
SIGUSR2
You can catch all of these except SIGKILL, but hopefully SIGKILL won't come up very often for you.
Note that your signal man page (man 7 signal) should give you the proper list for your system - this is the POSIX list, and may differ depending on your architecture.
You should not catch the signal and write the code to a pipe. This is both unnecessary and not failsafe.
Let me quote an answer from the question you linked to, to point out why it's not failsafe: "What makes you think that a SEGV hasn't already corrupted your program memory"
Now you may be wondering how to do it better, and why I've said it is "unnecessary".
The return code of the waitpid syscall can be checked using WIFSIGNALED() to determine whether the process was terminated normally or via a signal, and WTERMSIG() will return the signal number.
This is failsafe and it does not require a handler or a pipe. Plus, you don't need to worry what to catch, because it will report every signal that terminates your process.
It depends: whatever signal you like if that's useful to inform the user something bad just happened. However SIGKILL and SIGSTOP cannot be caught.

Building a Linux Debugger C

Trying to build a debugger in C for fuzzing.
Basically in linux, I just want to start a process via fork and then execve(), then monitor this process to see if it crashes after 1 second.
On linux, is this done via creating the process then monitoring the SIGNALs it generates for anything that looks like a crash? Or is it about monitoring the application and? I'm not sure.
Use the ptrace(2) system call:
While being traced, the child will stop each time a signal is
delivered, even if the signal is being ignored. (The exception is
SIGKILL, which has its usual effect.) The parent will be notified at
its next wait(2) and may inspect and modify the child process while it
is stopped. The parent then causes the child to continue, optionally
ignoring the delivered signal (or even delivering a different signal
instead).
The signals you should be interested in, regarding to the process having crashed are SIGSEGV (restricted memory access), SIGBUS (unaligned data access), SIGILL (illegal instruction), SIGFPE (illegal floating-point operation), etc.

POSIX signal behavior

If a process is currently stopped due to a SIGTRAP signal and it is sent a SIGSTOP signal via kill(), what would be the default behavior? Would the SIGSTOP be a pending signal that is delivered after the process continues again? Or will it just be discarded/ignored?
If the SIGSTOP is queued up, is there any way to remove it from the queue from outside of that process, such as in a tracing process?
From the signal(7) man page:
The signals SIGKILL and SIGSTOP cannot be caught, blocked, or ignored.
A simple test with an app stopped on a breakpoint and sending it a SIGSTOP shows gdb displaying some information when I hit 'next'. The signal was obviously delivered to the app. It cannot continue to be debugged until I send it a SIGCONT.
(gdb) next
Program received signal SIGSTOP, Stopped (signal).
fill (arr=0x7fffffffdff0, size=5) at tmp.cpp:28
(gdb) next
Program received signal SIGCONT, Continued.
fill (arr=0x7fffffffdff0, size=5) at tmp.cpp:28
(gdb) next
(gdb)
What do you mean 'stopped due to a SIGTRAP signal'? A SIGTRAP will not stop a process; by default it will terminate with a core dump, or you can change it to ignore the signal or call a signal handler, but in no case will the SIGTRAP stop the process by itself. You might have the process being traced by some other process (such as a debugger) with ptrace(2), in which case it will stop just before delivering the SIGTRAP, but in that case its under the control of the ptrace and won't continue until there's a PTRACE_CONT or other ptrace action to continue the process.

Resources