Why i can't catching SIGINT signal? - linux

Good day, i have next code:
server s;
namespace signals_handler
{
//sig_atomic_t is_stop=0;
void signal_handler(int sig)
{
if(sig==SIGHUP)
{
printf("recived :SIGHUP\n");
s.restart();
}
else if(sig==SIGINT)
{
printf("recived :SIGINT\n");
//is_stop = 1;
s.interupt();
}
}
}
int main(int argc, char* argv[])
{
signal(SIGHUP, signals_handler::signal_handler);
signal(SIGINT, signals_handler::signal_handler);
s.start();
s.listen();
return 0;
}
When i start execution of this code i can to catch SIGHUP, SIGINT not deliver for my application but debugger stoped in the "listen" function but not move to signalhandler function, Why this happens and what i doing wrongly?

It's normal. gdb catches the signal. From the manual:
Normally, gdb is set up to let the non-erroneous signals like SIGALRM
be silently passed to your program (so as not to interfere with their
role in the program's functioning) but to stop your program
immediately whenever an error signal happens. You can change these
settings with the handle command.
To change the behaviour, use:
handle SIGINT nostop pass
handle signal [keywords...]
Change the way gdb handles signal signal. signal can be the number of a signal or its name (with or without the ‘SIG’ at the beginning);
a list of signal numbers of the form ‘low-high’; or the word ‘all’,
meaning all the known signals. Optional arguments keywords, described
below, say what change to make.
The keywords allowed by the handle command can be abbreviated. Their
full names are:
nostop
gdb should not stop your program when this signal happens. It may still print a message telling you that the signal has come in.
stop
gdb should stop your program when this signal happens. This implies the print keyword as well.
print
gdb should print a message when this signal happens.
noprint
gdb should not mention the occurrence of the signal at all. This implies the nostop keyword as well.
pass
noignore
gdb should allow your program to see this signal; your program can handle the signal, or else it may terminate if the signal is fatal and not handled. pass and noignore are synonyms.
nopass
ignore
gdb should not allow your program to see this signal. nopass and ignore are synonyms.

Related

Why hangup signal is caught even with nohup?

package main
import (
"os"
"os/signal"
log "github.com/sirupsen/logrus"
"golang.org/x/sys/unix"
)
func main() {
sigs := make(chan os.Signal, 1)
signal.Notify(sigs, unix.SIGHUP)
go func() {
s := <-sigs
log.Info("OS signal: " + s.String())
}()
DoSomething()
}
I compiled the Go code above and executed with following command:
nohup ./build_linux > /dev/null 2>&1 &
But the process still catches HANGUP signal when I exit the terminal.
Seems like signal.Notify has higher priority, and nohup command has no effect.
What's going on and why nohup does not prevent sending hangup signal to process?
TL;DR
Check signal.Ignored() first:
if !signal.Ignored(unix.SIGHUP) {
signal.Notify(sigs, unix.SIGHUP)
}
Long
tkausl's comment has the correct answer: running:
nohup ./build_linux
from the command line launches the ./build_linux program with SIGHUP set to SIG_IGN (all of these signal names being generic Linux names, rather than Go package names). If you install your own handler for SIGHUP, this overrides the current setting of SIGHUP.
In general, in Unix/Linux programs, the correct pattern is to test whether the signal is currently ignored before (or as part of) installing a signal-catch function. If the signal is ignored, restore it to being ignored.
To make this process completely reliable, the most efficient correct pattern to use is:
hold off the signal (perhaps all signals);
install any desired handler, which returns the current disposition of the signal;
if the current disposition was SIG_IGN, return the disposition to SIG_IGN;
release the signal.
The holding-and-releasing is done with the Unix/Linux sigprocmask or pthread_sigmask system call. The one to use depends on whether you're using threads. Go of course does use threads; see, e.g., this patch to the Cgo runtime startup from 2013 (fixes issue #6811).
Since Go 1.11, which introduced signal.Ignored, you can just use that, as the Go runtime has already done all the appropriate hold / set-and-test / restore sequence at startup, and cached the result. One should definitely use this for SIGHUP so as to obey the nohup convention. One should generally use this for SIGINT and other keyboard signals as well, and there's almost1 no reason not to use it for all signals.1
1Jenkins, or some version or versions of Jenkins at least, apparently (incorrectly) sets all signals to be ignored at startup when running test suites.

GDB hangs when multi-threaded python extension is used to debug multi threaded program

I'm trying to develop a GDB python extension that defines a command that launches a new thread, in which the user can inspect an arbitrary type of variables. The skeleton of my python extension is this:
import gdb
import threading
def plot_thread():
import time
while True:
print('Placeholder for a window event loop.')
time.sleep(1)
pass
pass
class PlotterCommand(gdb.Command):
def __init__(self):
super(PlotterCommand, self).__init__("plot",
gdb.COMMAND_DATA,
gdb.COMPLETE_SYMBOL)
self.dont_repeat()
pass
def invoke(self, arg, from_tty):
plot_thread_instance=threading.Thread(target=plot_thread)
plot_thread_instance.daemon=True
plot_thread_instance.start()
pass
pass
PlotterCommand()
As can be seen, I define a plot command here. When I try to debug the following program, GDB will hang if I:
Put a breakpoint anywhere inside the procedure() thread (say, line 9, inside the while loop).
Run the command plot after gdb hits the breakpoint.
Run continue after that.
#include <iostream>
#include <thread>
using namespace std;
void procedure() {
cout << "before loop"<<endl;
while(1) {
cout << "loop iteration"<<endl;
}
}
int main() {
thread t(procedure);
t.join();
return 0;
}
The strangest thing is that, if I change this code to call procedure() without launching a thread, GDB never hangs (and the placeholder messages are still printed as I expect).
So far, I've tried to run this procedure with GDB versions 7.5.1 and 7.10, but I always experience the same behavior.
What am I doing wrong? Aren't daemon threads not supported by GDB? That doesn't seem to be in accordance with what the section 23.2.2.1 of the documentation is suggesting: GDB may not be thread safe, but I don't think it should hang after launching such a silly daemon thread.
From this blog post:
GDB uses this function (sigsuspend, the function where GDB hangs) to wait for new events from the application execution: when something occurs in the debuggee (see how debuggers work), the kernel will inform GDB of it by sending a SIGCHLD signal. When it's received, GDB awakes and check what happened.
However, the signal is delivered to GDB process, but not necessarily to its main thread. And it practise, it occurs often that it's delivered to the second thread, who doesn't care about it (that's the default behavior), and continues its life as if nothing occurred.
The solution is to configure the thread signal handling behavior, so that only the GDB main thread gets notified by these signals:
import gdb
import threading
import pysigset, signal # Import these packages!
def plot_thread():
import time
while True:
print('Placeholder for a window event loop.')
time.sleep(1)
pass
pass
class PlotterCommand(gdb.Command):
def __init__(self):
super(PlotterCommand, self).__init__("plot",
gdb.COMMAND_DATA,
gdb.COMPLETE_SYMBOL)
self.dont_repeat()
pass
def invoke(self, arg, from_tty):
with pysigset.suspended_signals(signal.SIGCHLD): # Disable signals here!
plot_thread_instance=threading.Thread(target=plot_thread)
plot_thread_instance.daemon=True
plot_thread_instance.start()
pass
pass
pass
PlotterCommand()
The pysigset package is required, and can be installed from pip (sudo pip install pysigset).

killall(1) equivalent system call or C library call

I have to stop the earlier instances of processes before starting a new instance. For this i need to system call or a C library call.
Presently i use "system("killall name"). This works but I want to replace this with any equivalent system(2)/library(3) calls. What is the option?
Also to remove files from directory as in "system("rm -f /opt/files*")",
what would be the alternate library(3)/system(2) call?
Pleas note * in file names, remove all files with one call.
regards,
AK
As far as I know there is no general way to do it, as there is no general way to get the pid by its process name.
You have to collect the pids of related processes and call the int kill(pid_t pid, int signo); function
At least you can try to check how its implemented by killall itself
A small addition from Ben's link, killall invokes following lines, i.e. collecting the pids of related process by find_pid_by_name function, implementation of which can be found here
pidList = find_pid_by_name(arg);
if (*pidList == 0) {
errors++;
if (!quiet)
bb_error_msg("%s: no process killed", arg);
} else {
pid_t *pl;
for (pl = pidList; *pl; pl++) {
if (*pl == pid)
continue;
if (kill(*pl, signo) == 0)
continue;
errors++;
if (!quiet)
bb_perror_msg("can't kill pid %d", (int)*pl);
}
}
You can see the implementation in busybox here: http://git.busybox.net/busybox/tree/procps/kill.c
You can also link with busybox as a shared library and invoke its kill_main instead of launching a separate process. It looks fairly well behaved for embedding like this -- always returns normally, never calls exit() -- although you may have difficultly getting error information beyond the return code. (But you aren't getting that via system() either).

Why doesn't waitid block until child terminates?

void *stack;
stack = malloc(STACK_SIZE);
if (-1 == clone(child_thread, stack + STACK_SIZE, 0, NULL)) {
perror("clone failed:");
}
while(waitid(P_ALL, 0, NULL, WEXITED) != 0){
perror("waitid failed:");
sleep(1);
}
The manual says:
If a child has already changed state, then these calls return
immediately. Otherwise they block until either a child changes state
But in fact it returns immediately :
waitid failed:: No child processes
waitid failed:: No child processes
...
Any advice?
You are using PID options. Look further in the man page:
The following Linux-specific options are for use with children created
using clone(2); they cannot be used with waitid():
__WCLONE
Wait for "clone" children only. If omitted then wait for "non-
clone" children only. (A "clone" child is one which delivers no
signal, or a signal other than SIGCHLD to its parent upon termi-
nation.) This option is ignored if __WALL is also specified.
__WALL (Since Linux 2.4) Wait for all children, regardless of type
("clone" or "non-clone").
__WNOTHREAD
(Since Linux 2.4) Do not wait for children of other threads in
the same thread group. This was the default before Linux 2.4.
I do not know the specifics of what you are trying to get done here, but by using waitid in the following way might help:
#include <sys/types.h>
#include <sys/wait.h>
...
siginfo_t signalInfo;
waitid(P_ALL, 0, &signalInfo, WEXITED | WSTOPPED | WNOWAIT | WNOHANG);
Then check for the following in signalInfo to know what happened whenever child exits:
signalInfo.si_signo : For Signal Number
signalInfo.si_code : Usually SIGCHLD
signalInfo.si_errno) : Any error code set
signalInfo.si_status : For exit code of the child code
Note: Using WNOWAIT makes the OS preserve the child process resource usage even after it is killed. You may/may not use this option. If you do, you will have to explicitly call waitid on the child again without the WNOWAIT option.
Reference: See man pages for waitid for more information on this.

Is it possible to run the main QT program on a thread?

I have a simple QT object. When I execute the code below the control is transfer to the QT object, but I would like to make the QT part work like a thread.
int main(int argc, char *args[])
{
gui *GUI;
//// before call
QApplication app(argc,args);
GUI = new gui();
GUI->show();
////i want to be able to do stuff here in parallel with the QT code.
// If I spawn a thead here or give a simple printf statement here
// or before call it executes only after GUI exits
return app.exec();
}
Make sure you not only create the thread but actually start it. Also, a printf() statement will execute before the GUI shows unless you forgot to terminate the string with a newline (\n).

Resources