This is the mail archive of the
ecos-bugs@sourceware.org
mailing list for the eCos project.
[Bug 1002143] New: sigwait does not wake up on blocked signals.
- From: bugzilla-daemon at ecoscentric dot com
- To: unassigned at bugs dot ecos dot sourceware dot org
- Date: Wed, 20 Apr 2016 04:40:55 +0000
- Subject: [Bug 1002143] New: sigwait does not wake up on blocked signals.
- Authentication-results: sourceware.org; auth=none
- Authentication-results: mail.ecoscentric.com; dkim=permerror (bad message/signature format)
- Auto-submitted: auto-generated
- Dkim-filter: OpenDKIM Filter v2.10.3 mail.ecoscentric.com 85208A8914F
Please do not reply to this email, use the link below.
http://bugs.ecos.sourceware.org/show_bug.cgi?id=1002143
Bug ID: 1002143
Summary: sigwait does not wake up on blocked signals.
Product: eCos
Version: 3.0
Target: All
Architecture/Host_ Other
OS:
Status: UNCONFIRMED
Severity: enhancement
Priority: low
Component: POSIX
Assignee: unassigned@bugs.ecos.sourceware.org
Reporter: ehoffman@positronaccess.com
QA Contact: ecos-bugs@ecos.sourceware.org
CC: ecos-bugs@ecos.sourceware.org
Hello
I came into the same problem as discussed in 2009 in the mailing list
Ref: https://sourceware.org/ml/ecos-discuss/2009-09/msg00159.html
The discussion thread ended up short with no real satisfactory answer, and I do
think the original question is really pointing a bug.
Basically, the issue is that if you have a pthread, and in that POSIX thread
you block some signals (SIGUSR1 for example), and you do a sigwait, waiting for
that signal, then the thread is supposed to wait for that signal to be in the
signal queue, and return when the signal is present in the queue (removing it
from the signal queue). It is normal behavior to wait on blocked signals,
sigwait POSIX documentation say that the signal should be blocked before
calling sigwait. This is to prevent signal handler from dispatching the signal
and removing it from the queue:
[...]If no signal in set is pending at the time of the call, the thread shall
be suspended until one or more becomes pending. The signals defined by set
shall have been blocked at the time of the call to sigwait(); otherwise, the
behavior is undefined[...]
So, the normal usage is is as follow:
- Thread X (pthread) block a specific signal, using pthread_sigmask().
- Thread X call sigwait(), waiting for that signal to be present in the signal
set/queue.
- Thread Y call pthread_kill(), sending signal to thread X.
- Thread X get the signal in the queue (or from the signal set). Since the
signal is blocked, no signal handler is called. However, since you have called
sigwait(), the sigwait() function returns and remove the signal from the queue.
If thread Y sends the signal to thread X before thread X call sigwait(), the
signal is set in thread X. Nothing happen since it's blocked in thread X with
the previous call to pthread_sigmask(). However, as soon as thread X call
sigwait(), sigwait() returns immediately (removing the signal from the queue).
That behavior is properly respected by eCos.
If thread X call sigwait() before it receive a signal, it goes to sleep,
waiting for signal. When thread Y send signal to thread X (using
pthread_kill), the signal is then put in thread Y signal queue (or signal set).
Thread Y then wake up and "consume" the signal, returning from sigwait().
That is NOT working in eCos, and it's what's discussed in the mailing list I
mentioned above.
I also checked and confirmed that this behavior seem to be related to the code
in signal.cxx:
if( thread != NULL )
{
sigaddset( &thread->sigpending, signo );
// just wake the thread up now if it's blocked somewhere
if ((thread->sigpending & ~thread->sigmask) != 0)
{
thread->thread->set_asr_pending();
thread->thread->release();
}
}
This code will wake up the thread ONLY if the signal is not blocked in the
thread. This behavior is erroneous. If the signal is blocked in the receiving
thread, it MUST be awaken if the receiving thread is waiting for signal
(sigwait/sigtimedwait). However the behavior is correct if the receiving
thread is sleeping for other reasons.
So, to correct the behavior, a new state variable is required on the receiving
thread to indicate that the thread is actively waiting for signal. The thread
must be awaken if either the signal is unblocked, or if the thread is waiting
for the specified signal. Something that goes like:
if ((thread->sigpending & (~thread->sigmask | thread->sigwaitset)) != 0)
...
thread->sigwaitset should be set before putting thread to sleep (before calling
signal_sigwait.wait()), and cleared after awaking from sleep.
This is applicable to both cyg_sigqueue() function and in
cyg_posix_pthread_release_thread() function in signal.cxx.
Also, the sigwait family can return EAGAIN in case of timeout (sigtimedwait)
and EINTR in case of interruption by a signal other than the signals the
sigwait/sigtimedwait was waiting for (which wasn't blocked). eCos now only
have hardcoded EAGAIN. EAGAIN must only be used for when timeout occur.
Otherwise, EINTR must be returned. So when returning from the
signal_sigwait.wait() function, the wake reason must be checked (and not just
hardcode EGAIN).
Regards,
Eric Hoffman
--
You are receiving this mail because:
You are the assignee for the bug.