why is POSIX::SigSet is needed here? - linux

!/usr/bin/env perl
use POSIX;
my $sig_set = POSIX::SigSet->new(POSIX::SIGINT);
my $sig_act = POSIX::SigAction->new(sub { print "called\n"; exit 0 },$sig_set);
POSIX::sigaction(SIGINT,$sig_act);
sleep(15);
Why do I need to use POSIX::SigSet if I already tell POSIX::sigaction that I want SIGINT?
Basically I'm trying to respond with my coderef to each of the signal I add to SigSet, looking at POSIX::sigaction signature, it must accept a singal as the first parametner, which doesnt seems reasonable to be if I already tell POSIX::SigAction about my POSIX::SigSet.
I'm sure I am missing something here.
thanks,

The answer to your question
The POSIX::SigSet specifies additional signals to mask off (to ignore) during the execution of your signal handler sub. It corresponds to the sa_mask member of the underlying struct passed to the C version of sigaction.
Now, SIGINT (well, the first argument to sigaction) will be masked off by default, unless you explicitly request otherwise via the SA_NODEFER.
A better approach?
However, if all you want to do it to register a signal handler whose execution won't be interrupted by the signal for which it was registered (e.g., don't allow SIGINT during your SIGINT handler), you can skip the POSIX module entirely:
$SIG{INT} = sub { print "called\n"; exit 0; }; # Won't be interrupted by SIGINT
Where it can, Perl's signal dispatching emulates the traditional UNIX semantics of blocking a signal during its handler execution. (And on Linux, it certainly can. sigprocmask() is called before executing the handler, and then a scope-guard function is registered to re-allow that signal at the end of the user-supplied sub.)

Related

Does join in perl threads block SIGALRM?

I have a small sample program that hangs on perl 5.16.3. I am attempting to use an alarm to trigger if two threads don't finish working in time in a much more complicated program, but this boils down the gist of it. I know there's plenty of other ways to do this, but for the sake of argument, let's say I'm stuck with the code the way it is. I'm not sure if this is a bug in perl, or something that legitimately shouldn't work.
I have researched this on the Internet, and it seems like mixing alarms and threads is generally discouraged, but I've seen plenty of examples where people claim that this is a perfectly reasonable thing to do, such as this other SO question, Perl threads with alarm. The code provided in the accepted answer on that question also hangs on my system, which is why I'm wondering if maybe this is something that's now broke, at least as of 5.16.3.
It appears that in the code below, if I call join before the alarm goes off, the alarm never triggers. If I replace the join with while(1){} and go into a busy-wait loop, then the alarm goes off just fine, so it appears that join is blocking the SIGALRM for some reason.
My expectation is that the join happens, and then a few seconds later I see "Alarm!" printed on the screen, but this never happens, so long as that join gets called before the alarm goes off.
#!/usr/bin/env perl
use strict;
use warnings;
use threads;
sub worker {
print "Worker thread started.\n";
while(1){}
}
my $thread = threads->create(\&worker);
print "Setting alarm.\n";
$SIG{ALRM} = sub { print "Alarm!\n" };
alarm 2;
print "Joining.\n";
$thread->join();
The problem has nothing to do with threads. Signals are only processed between Perl ops, and join is written in C, so the signal will only be handled when join returns. The following demonstrates this:
#!/usr/bin/env perl
use strict;
use warnings;
use threads;
sub worker {
print "Worker thread started.\n";
for (1..5) {
sleep(1);
print(".\n");
}
}
my $thread = threads->create(\&worker);
print "Setting alarm.\n";
$SIG{ALRM} = sub { print "Alarm!\n" };
alarm 2;
print "Joining.\n";
$thread->join();
Output:
Setting alarm.
Joining.
Worker thread started.
.
.
.
.
.
Alarm!
join is essentially a call to pthread_join. Unlike other blocking system calls, pthread_join does not get interrupted by signals.
By the way, I renamed $tid to $thread since threads->create returns a thread object, not a thread id.
I'm going to post an answer to my own question to add some detail to ikegami's response above, and summarize our conversation, which should save future visitors from having to read through the huge comment trail it collected.
After discussing things with ikegami, I went and did some more reading on perl signals, consulted some other perl experts, and discovered the exact reason why join isn't being "interrupted" by the interpreter. As ikegami said, signals only get delivered in between perl operations. In perl, this is called Deferred Signals, or Safe Signals.
Deferred Signals were released in 5.8.0, back in 2002, which could be one of the reasons I was seeing older posts on the Net which don't appear to work. They probably worked with "unsafe signals", which act more like signal delivery that we're used to in C. In fact, as of 5.8.1, you can turn off deferred signal delivery by setting the environment variable PERL_SIGNALS=unsafe before executing your script. When I do this, the threads::join call is indeed interrupted as I was expecting, just as pthread_join is interrupted in C in this same scenario.
Unlike other I/O operations, like read, which returns EINTR when a signal interrupts it, threads::join doesn't do this. Under the hood it's a call to the C library call pthread_join, which the man page confirms does not return EINTR. Under deferred signals, when the interpreter gets the SIGALRM, it schedules delivery of the signal, deferring it, until the threads::join->pthread_join library call returns. Since pthread_join doesn't "interrupt" and return EINTR, my SIGALRM is effectively being swallowed by the threads::join. With other I/O operations, they would "interrupt" and return EINTR, giving the perl interpreter a chance to deliver the signal and then restart the system call via SA_RESTART.
Obviously, running in unsafe signals mode is probably a Bad Thing, so as an alternative, according to perlipc, you can use the POSIX module to install a signal handler directly via sigaction. This then makes the one particular signal "unsafe".

What is the actual signal behind ERR

I've read in several places (including SO) that -e is considered "poor form" and is unreliable for exiting a script on any error. A better way to handle errors seems to be using trap, as such:
trap "echo there was an error; exit 1;" ERR
I can't seem to locate in the man pages what signal ERR is actually? I'm assuming it's SIGQUIT but I can't find for sure.
man 7 signal
only has the normal signals you would expect SIGTERM SIGQUIT SIGINT, etc.
man trap
has references to ERR signal, but doesn't seem to define it.
ex: "A trap on ERR, if set, is executed before the shell exits."
man bash
is similar to man trap in that is makes references to ERR but doesn't define it from what I've seen.
What is the actual signal behind the shortcut ERR? (in normal signals as seen in man 7 signal).
I'd prefer to trap the actual signal name instead of the shorthand version, although I realize they would produce the same results (catching any error from a command in a script then throwing to the handler).
There is no signal corresponding to the trap signal specification ERR.
ERR is one of the signal specifications implemented internally by bash. [Note 1] If trap ERR is enabled, then bash will invoke the corresponding handler in exactly the same cases as it would have exited had set -e been enabled. (Consequently, it is no more "reliable" then set -e but it is a lot more flexible.)
Other special trap names which do not correspond to any signal are EXIT, DEBUG and RETURN.
help trap will explain the meaning of these signal specifications.
Notes:
Actually, all of the signal specifications are implemented by bash, but most of them are implemented by bash trapping the signal and then executing the signal handler. The special ones just involve executing the signal handler.

Timing traps in a shell script

I have a shell script background process that runs "nohupped". This process shall receive signals in a trap, but when playing around with some code, I noticed that some signals are ignored if the interval between them is too small. The execution of the trap function takes too much time and therefore the subsequent signal goes
unserved. Unfortunately, the trap command doesn't have some kind of signal queue, that's why I am asking: What is the best way to solve this problem?
A simple example:
function receive_signal()
{
local TIMESTAMP=`date '+%Y%m%d%H%M%S'`
echo "some text" > $TIMESTAMP
}
trap receive_signal USR1
while :
do
sleep 5
done
The easiest change, without redesigning your approach, is to use realtime signals, which queue.
This is not portable. Realtime signals themselves are an optional extension, and shell and utility support for them are not required by the extension in any case. However, it so happens that the relevant GNU utilities on Linux — bash(1) and kill(1) — do support realtime signals in a commonsense way. So, you can say:
trap sahandler RTMIN+1
and, elsewhere:
$ kill RTMIN+1 $pid_of_my_process
Did you consider multiple one line trap statements? One for each signal you want to block or process?
trap dosomething 15
trap segfault SEGV
Also you want to have the least possible code in a signal handler for the reason you just encountered.
Edit - for bash you can code your own error handling / signal handling in C, or anything else using modern signal semantics if you want with dynamically loadable modules:
http://cfajohnson.com/shell/articles/dynamically-loadable/

perl: thread termination blocked by user input

I have made a program which can terminate in 2 ways, either user enters a string say- "kill" or a specific thread signals SIGINT.
In this terminator thread I have a statement(to catch "kill"):
$a = <>;
followed by a 'return;'
I have appropriate signal handler (for INT) too on the top which does:
print "signal received\n";
threads->exit();
but in the case of automatic termination(that is SIGINT is sent from other thread), the print stmt doesn't come until I press some key, no matter how long I wait. I suppose <> is blocking.
Could someone please tell how can I provide some sort of input to <> in the auto termination case so as to see the results immediately.
Thanks.
You can't do what you're trying to do, the way you're trying to do it. If a file is being read, and 'pending input' then process goes into an uninterruptible wait state. You basically can't interrupt it via signalling at this point. Uninterruptible waits are a kernel thing and the key point is preventing file corruption.
To do what you're trying to do, you would probably need to make use of something like IO::Select and the can_read function. You can test which filehandles are ready for IO, in a polling loop - this polling loop is interruptible by kill signals.
Alternatively, instead of using a filehandle read, you can use Term::ReadKey which will allow you to trap a keypress in a nonblocking fashion

How to implement a thread safe timer on linux?

As we know, doing things in signal handlers is really bad, because they run in an interrupt-like context. It's quite possible that various locks (including the malloc() heap lock!) are held when the signal handler is called.
So I want to implement a thread safe timer without using signal mechanism.
How can I do?
Sorry, actually, I'm not expecting answers about thread-safe, but answers about implementing a timer on Unix or Linux which is thread-safe.
Use usleep(3) or sleep(3) in your thread. This will block the thread until the timeout expires.
If you need to wait on I/O and have a timer expire before any I/O is ready, use select(2), poll(2) or epoll(7) with a timeout.
If you still need to use a signal handler, create a pipe with pipe(2), do a blocking read on the read side in your thread, or use select/poll/epoll to wait for it to be ready, and write a byte to the write end of your pipe in the signal handler with write(2). It doesn't matter what you write to the pipe - the idea is to just get your thread to wake up. If you want to multiplex signals on the one pipe, write the signal number or some other ID to the pipe.
You should probably use something like pthreads, the POSIX threads library. It provides not only threads themselves but also basic synchronization primitives like mutexes (locks), conditions, semaphores. Here's a tutorial I found that seems to be decent:
http://www.yolinux.com/TUTORIALS/LinuxTutorialPosixThreads.html
For what it's worth, if you're totally unfamiliar with multithreaded programming, it might be a little easier to learn it in Java or Python, if you know either of those, than in C.
I think the usual way around the problems you describe is to make the signal handlers do only a minimal amount of work. E.g. setting some timer_expired flag. Then you have some thread that regularly checks whether the flag has been set, and does the actual work.
If you don't want to use signals I suppose you'd have to make a thread sleep or busy-wait for the specified time.
Use a Posix interval timer, and have it notify via a signal. Inside the signal handler function almost none of C's functions, like printf() can be used, as they aren't re-entrant.
Use a single global flag, declared static volatile for your signal handler to manipulate. The handler should literally have this one line of code, and NOTHING else; This flag should impact the flow control elsewhere in the 1 & Only thread in the program.
static volatile bool g_zig_instead_of_zag_flg = false;
...
void signal_handler_fnc()
g_zig_instead_of_zag_flg = true;
return
int main() {
if(false == g_zig_instead_of_zag) {
do_zag();
} else {
do_zig();
g_zig_instead_of_zag = false;
return 0;
}
Michael Kerrisk's The Linux Programming Interface has examples of both methods, and a few more, but the examples come with a lot of his own private functions you have to get working, and the examples carefully avoid many of the gotchas they should explore, so not great.
Using the Poxix interval timer that notifies via a thread makes everything a lot worse, and AFAICT, that notification method is pretty much useless. I only say pretty much because I am allowing that there may be SOME case where doing nothing in the main() thread, and everything in the handler thread is useful, but I sure can't think of any such case.

Resources