comp.lang.ada
 help / color / mirror / Atom feed
* GNAT: Setting SIGPIPE to SIG_IGN
@ 2002-08-31  9:36 Florian Weimer
  2002-08-31 21:13 ` Warren W. Gay VE3WWG
  0 siblings, 1 reply; 6+ messages in thread
From: Florian Weimer @ 2002-08-31  9:36 UTC (permalink / raw)


I want to instruct the GNAT run-time library that it sets the SIGPIPE
handler to SIG_IGN, so that system calls such as read() return EPIPE
instead of delivering a signal.

This might sound like a silly question (I can write the necessary call
to signal(2) myself), but I don't want to work around the GNAT
run-time library.  Any suggestions?  The RM interfaces do not appear
to be helpful here because I think that if no handler is attached, the
default handler is invoked, which is not what I want.



^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: GNAT: Setting SIGPIPE to SIG_IGN
  2002-08-31  9:36 GNAT: Setting SIGPIPE to SIG_IGN Florian Weimer
@ 2002-08-31 21:13 ` Warren W. Gay VE3WWG
  2002-09-01  0:20   ` Darren New
  2002-09-01 10:16   ` Florian Weimer
  0 siblings, 2 replies; 6+ messages in thread
From: Warren W. Gay VE3WWG @ 2002-08-31 21:13 UTC (permalink / raw)


Florian Weimer wrote:
> I want to instruct the GNAT run-time library that it sets the SIGPIPE
> handler to SIG_IGN, so that system calls such as read() return EPIPE
> instead of delivering a signal.

Actually, I think you mean that read(2) returns EINTR (or EAGAIN
on some platforms). EPIPE is returned when you write to a
pipe without a reader.

> This might sound like a silly question (I can write the necessary call
> to signal(2) myself), but I don't want to work around the GNAT
> run-time library.  Any suggestions?  

I know what you're driving at. You'll need to know what GNAT is doing
by default. I suspect that the SIG_DFL is the default for the SIGPIPE
signal. SIG_DFL's meaning varies by signal on a particular host. But by
default, for SIGPIPE, it defaults to delivering the signal usually.

You can approach this from two angles IMO:

1) Establish a signal handler in Ada, and ignore the signal (this will
    "catch the signal", and still cause EINTR to be returned for blocked
    system calls like read(2), when the handler returns).
2) Deal with it in C terms, using SIG_IGN, which will have the same
    effect without having to specify a handler (the less code approach).

> The RM interfaces do not appear
> to be helpful here because I think that if no handler is attached, the
> default handler is invoked, which is not what I want.

Actually, I believe there is no handler at all (the process just
aborts, based upon a O/S "system" action specified by SIG_DFL for
SIGPIPE).

I believe GNAT leaves the setting as SIG_DFL. You can check this by
calling a C program that retrieves the current setting and comparing
it against SIG_DFL.  If this is the case, then GNAT is doing nothing
with the signal (not handling it), but the O/S is permitted to raise
the signal (the default system action occurs).

I havn't yet fully dug into this, but I do believe there was a signal
names related change after GNAT 3.13p, since my signal code would not
compile on gcc-3.1.1 when I tried it (I think the signal name definitions
moved to a child package.) So approach # 2 might be "more portable",
but I am just guessing with a poor memory ;-)

-- 
Warren W. Gay VE3WWG
http://home.cogeco.ca/~ve3wwg




^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: GNAT: Setting SIGPIPE to SIG_IGN
  2002-08-31 21:13 ` Warren W. Gay VE3WWG
@ 2002-09-01  0:20   ` Darren New
  2002-09-01 10:16   ` Florian Weimer
  1 sibling, 0 replies; 6+ messages in thread
From: Darren New @ 2002-09-01  0:20 UTC (permalink / raw)


"Warren W. Gay VE3WWG" wrote:
> 
> Florian Weimer wrote:
> > I want to instruct the GNAT run-time library that it sets the SIGPIPE
> > handler to SIG_IGN, so that system calls such as read() return EPIPE
> > instead of delivering a signal.
> 
> Actually, I think you mean that read(2) returns EINTR (or EAGAIN
> on some platforms). EPIPE is returned when you write to a
> pipe without a reader.

If you read from a pipe whose other end has been closed, I'm pretty sure you
always get EOF, yes? Of course, if you get a different signal while blocked
on the pipe, you of course get the same signal you'd get from any blocking
operation that gets interruped by a signal.

It's writing to a broken pipe that raises SIGPIPE, and that's only because
of the funky way that UNIX shells cause signals to be delivered to
processes. (Basically, the original V7 shells wound up having the last
process of a pipeline being the direct child, and the shell passed signals
on to it, so it died, and the other processes in the pipeline died as they
tried to write to the broken pipe. Obviated by the invention of control
terminals.)

-- 
Darren New 
San Diego, CA, USA (PST). Cryptokeys on demand.
   ** http://images.fbrtech.com/dnew/ **

Try our EbolaBurgers...
      So tender they melt in your mouth.



^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: GNAT: Setting SIGPIPE to SIG_IGN
  2002-08-31 21:13 ` Warren W. Gay VE3WWG
  2002-09-01  0:20   ` Darren New
@ 2002-09-01 10:16   ` Florian Weimer
  2002-09-02  2:27     ` Warren W. Gay VE3WWG
  1 sibling, 1 reply; 6+ messages in thread
From: Florian Weimer @ 2002-09-01 10:16 UTC (permalink / raw)


"Warren W. Gay VE3WWG" <ve3wwg@cogeco.ca> writes:

> Florian Weimer wrote:
>> I want to instruct the GNAT run-time library that it sets the SIGPIPE
>> handler to SIG_IGN, so that system calls such as read() return EPIPE
>> instead of delivering a signal.
>
> Actually, I think you mean that read(2) returns EINTR (or EAGAIN
> on some platforms). EPIPE is returned when you write to a
> pipe without a reader.

It depends on the protocol.  I believe that TCP implementation behaves
in the same way (as you describe it), but some other networking
protocol implementations deliver SIGPIPE even on recvmsg() etc.

>> This might sound like a silly question (I can write the necessary call
>> to signal(2) myself), but I don't want to work around the GNAT
>> run-time library.  Any suggestions?
>
> I know what you're driving at. You'll need to know what GNAT is doing
> by default. I suspect that the SIG_DFL is the default for the SIGPIPE
> signal. SIG_DFL's meaning varies by signal on a particular host. But by
> default, for SIGPIPE, it defaults to delivering the signal usually.

The default for SIGPIPE is to terminate the thread, which is a bit too
drastic for my taste.

> You can approach this from two angles IMO:
>
> 1) Establish a signal handler in Ada, and ignore the signal (this will
>     "catch the signal", and still cause EINTR to be returned for blocked
>     system calls like read(2), when the handler returns).

It will cause EPIPE to be returned, so it works the way I want.  (I
assumed that setting the handler to SIG_IGN had some magic side
effect, similar to other signals, but this is not the case.)

However, this pulls in the tasking run-time library which has got very
problematic side effects, at leat on GNU/Linux.

> 2) Deal with it in C terms, using SIG_IGN, which will have the same
>     effect without having to specify a handler (the less code approach).

There is a problem with LinuxThreads (the threading implementation
provided by the GNU libc): signal handlers are thread-specific, so it
is not sufficient to set the handler in a single thread (GNAT
compensates for this, but you would have to do it on your own here).



^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: GNAT: Setting SIGPIPE to SIG_IGN
  2002-09-01 10:16   ` Florian Weimer
@ 2002-09-02  2:27     ` Warren W. Gay VE3WWG
  2002-09-02 22:39       ` Florian Weimer
  0 siblings, 1 reply; 6+ messages in thread
From: Warren W. Gay VE3WWG @ 2002-09-02  2:27 UTC (permalink / raw)


Florian Weimer wrote:
> "Warren W. Gay VE3WWG" <ve3wwg@cogeco.ca> writes:
>>Florian Weimer wrote:
>>
>>>I want to instruct the GNAT run-time library that it sets the SIGPIPE
>>>handler to SIG_IGN, so that system calls such as read() return EPIPE
>>>instead of delivering a signal.
>>
>>Actually, I think you mean that read(2) returns EINTR (or EAGAIN
>>on some platforms). EPIPE is returned when you write to a
>>pipe without a reader.
> 
> It depends on the protocol.  I believe that TCP implementation behaves
> in the same way (as you describe it), but some other networking
> protocol implementations deliver SIGPIPE even on recvmsg() etc.

Interesting. It doesn't sound unreasonable.

>>>This might sound like a silly question (I can write the necessary call
>>>to signal(2) myself), but I don't want to work around the GNAT
>>>run-time library.  Any suggestions?
>>
>>I know what you're driving at. You'll need to know what GNAT is doing
>>by default. I suspect that the SIG_DFL is the default for the SIGPIPE
>>signal. SIG_DFL's meaning varies by signal on a particular host. But by
>>default, for SIGPIPE, it defaults to delivering the signal usually.
> 
> The default for SIGPIPE is to terminate the thread, which is a bit too
> drastic for my taste.

Yes.

>>You can approach this from two angles IMO:
>>
>>1) Establish a signal handler in Ada, and ignore the signal (this will
>>    "catch the signal", and still cause EINTR to be returned for blocked
>>    system calls like read(2), when the handler returns).
> 
> It will cause EPIPE to be returned, so it works the way I want.  (I
> assumed that setting the handler to SIG_IGN had some magic side
> effect, similar to other signals, but this is not the case.)
> 
> However, this pulls in the tasking run-time library which has got very
> problematic side effects, at leat on GNU/Linux.

Hmmm, I see.

>>2) Deal with it in C terms, using SIG_IGN, which will have the same
>>    effect without having to specify a handler (the less code approach).
> 
> There is a problem with LinuxThreads (the threading implementation
> provided by the GNU libc): signal handlers are thread-specific, so it
> is not sufficient to set the handler in a single thread (GNAT
> compensates for this, but you would have to do it on your own here).

Is there anything useful you can learn from the "GNAT compensation"
that might help?

I'm afraid I don't see an easy solution. I think the approach
I would take is to attempt to solve the "problematic side effects" in
the "tasking run-time library". But this probably doesn't work well
for a project that must "port" to multiple platforms (you haven't said
much about the project requirements), or port to many future releases
of Linux. (One possibly useless suggestion is to try FreeBSD instead ;-)

The only other possibility would be if you knew of a way to iterate
over all known threads in C. I am not aware of a Linux way to do this,
though there might very well be (perhaps one way is to walk the
errno array implementation, checking for valid threads).

Beyond that, I can't think of any further useful advice. I do
believe that you do have an interesting problem.

In fact, this problem interests me, now that I think of it.
Any GNAT project written for Linux that must intercept SIGINT
(for example), has a challenge ahead of them if tasking is
used and the library has significant side-effects.

Would you be willing to elaborate on the "problematic side effects"?
Are they problems for your typical Linux tasking app in GNAT? I
currently develop on FreeBSD, but by no means want to limit my
Open Source projects to one platform.
-- 
Warren W. Gay VE3WWG
http://home.cogeco.ca/~ve3wwg




^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: GNAT: Setting SIGPIPE to SIG_IGN
  2002-09-02  2:27     ` Warren W. Gay VE3WWG
@ 2002-09-02 22:39       ` Florian Weimer
  0 siblings, 0 replies; 6+ messages in thread
From: Florian Weimer @ 2002-09-02 22:39 UTC (permalink / raw)


"Warren W. Gay VE3WWG" <ve3wwg@cogeco.ca> writes:

> Is there anything useful you can learn from the "GNAT compensation"
> that might help?

> I'm afraid I don't see an easy solution. I think the approach
> I would take is to attempt to solve the "problematic side effects" in
> the "tasking run-time library".

Ugh, I can't do that.  If tasking is activated, setuid(2) and similar
system calls do not work reliable on GNU/Linux: Credentials are thread
attributes, not process attributes as required.  And there's somethign
which makes matters even worse: The pthreads library uses signals
for communication with the management thread, and if I change the
credentials, the signals cannot be delivered any longer because the
permission check fails, and the program just stops.  This problem is
triggered not only by the active use of tasking, it's sufficient to
declare a single protected object.

> But this probably doesn't work well for a project that must "port"
> to multiple platforms (you haven't said much about the project
> requirements),

I'd like to have as few as GNU/Linux dependencies as possible.  In
fact, last weekend, I've made some changes (see my other message about
C expression evaluation using autoconf) which should port my little
pet project to any POSIX platform on which GNAT binaries can run.

> or port to many future releases of Linux.

Linux isn't the problem here, it's the threading implementation in GNU
libc.  I wouldn't have to face this problem if I was using FSU
Threads, for example, or if I'd wait a few months (years?) until the
GNU libc implementation is conforming to POSIX.

> (One possibly useless suggestion is to try FreeBSD instead ;-)

Perhaps after the first big security incident Debian has to
experience. ;-)

> Beyond that, I can't think of any further useful advice. I do
> believe that you do have an interesting problem.

Well, fortunately my fundamental assumption is wrong: signal handlers
are not thread specific, although signals are always thread-specific
(which differs from what POSIX says).  As a result, I can call
signal(SIGPIPE, SIG_IGN) during elaboration.  Case closed.

(Well, I better write a test case for that, but looking at the actual
source code, I think this should work, and all the complexity isn't
required.)



^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2002-09-02 22:39 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2002-08-31  9:36 GNAT: Setting SIGPIPE to SIG_IGN Florian Weimer
2002-08-31 21:13 ` Warren W. Gay VE3WWG
2002-09-01  0:20   ` Darren New
2002-09-01 10:16   ` Florian Weimer
2002-09-02  2:27     ` Warren W. Gay VE3WWG
2002-09-02 22:39       ` Florian Weimer

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox