Discussion:
async-signal safety read/ readv/ recvmsg
(too old to reply)
Rainer Weikusat
2021-03-01 21:39:33 UTC
Permalink
To my bewilderment, I just discovered that both read and recvmsg are
required to be async-signal safe but readv isn't (some goes for
output routines).

Does someone know a reason for this bizarrely asymetrical arrangement?
Scott Lurndal
2021-03-01 23:09:14 UTC
Permalink
Post by Rainer Weikusat
To my bewilderment, I just discovered that both read and recvmsg are
required to be async-signal safe but readv isn't (some goes for
output routines).
Does someone know a reason for this bizarrely asymetrical arrangement?
Probably becomes some early implementations were library implementations
built on calling read for each iovec element.
Kaz Kylheku
2021-03-01 23:24:43 UTC
Permalink
Post by Scott Lurndal
Post by Rainer Weikusat
To my bewilderment, I just discovered that both read and recvmsg are
required to be async-signal safe but readv isn't (some goes for
output routines).
Does someone know a reason for this bizarrely asymetrical arrangement?
Probably becomes some early implementations were library implementations
built on calling read for each iovec element.
Even so, if that is all done with local variables, it just fails to be
atomic with respect to signals; it is not unsafe.

A multi-read readv could be interrupted by an async signal, which could
use that readv just fine.

Maybe the thinking is that the handler could invoke a readv on the
same descriptor. In that case, the bytes emerging in the iov comprise
a garbage sequence which never occurred in the stream.

Still, interrupting code and reading from the same descriptor is
dodgy, even with atomic reads.
--
TXR Programming Language: http://nongnu.org/txr
Cygna: Cygwin Native Application Library: http://kylheku.com/cygnal
Kaz Kylheku
2021-03-01 23:17:33 UTC
Permalink
Post by Rainer Weikusat
To my bewilderment, I just discovered that both read and recvmsg are
required to be async-signal safe but readv isn't (some goes for
output routines).
Eek.
Post by Rainer Weikusat
Does someone know a reason for this bizarrely asymetrical arrangement?
If it's not simply an oversight, could it have something to do with some
dumb user space simulations of these functions?

If you don't actually have readv as a kernel primitive, what can
go wrong, signal-wise?

The user space implementation has to intercept errno to determine
success, and then do the copying from the linear buffer to the iovec.

Well, so what?

The behavior is undefined if an unsafe function is interrupted by an
async signal handler which then calls an unsafe function, so what we
have to think about is how an interrupted and re-entered readv
could misbehave.

Looking at errno could be a problem if an async signal handler doesn't
save it and restore it, but that is generally required. POSIX says
"Operations which obtain the value of errno and operations which assign
a value to errno shall be async-signal-safe, provided that the
signal-catching function saves the value of errno upon entry and
restores it before it returns."

If we do a siglongjmp out of the handler which interrupted a readv,
the program can tell that its buffers were clobbered, though the
readv did not complete. But that's no what async safety is documented
as being about; that's more along the lines of atomicity in the
face of a signal.
--
TXR Programming Language: http://nongnu.org/txr
Cygna: Cygwin Native Application Library: http://kylheku.com/cygnal
Kaz Kylheku
2021-03-01 23:28:42 UTC
Permalink
Post by Kaz Kylheku
Post by Rainer Weikusat
To my bewilderment, I just discovered that both read and recvmsg are
required to be async-signal safe but readv isn't (some goes for
output routines).
Eek.
Post by Rainer Weikusat
Does someone know a reason for this bizarrely asymetrical arrangement?
If it's not simply an oversight, could it have something to do with some
dumb user space simulations of these functions?
If you don't actually have readv as a kernel primitive, what can
go wrong, signal-wise?
The user space implementation has to intercept errno to determine
success, and then do the copying from the linear buffer to the iovec.
Ah, but if the goal of the faked out readv implementation was to
minimize the calls to read, at the expense of copying, it would have to
get a temporary linear buffer from somewhere. If that somewhere is
malloc, then you have an async problem right there.
Geoff Clare
2021-03-02 13:20:56 UTC
Permalink
Post by Rainer Weikusat
To my bewilderment, I just discovered that both read and recvmsg are
required to be async-signal safe but readv isn't (some goes for
output routines).
Eek.
Post by Rainer Weikusat
Does someone know a reason for this bizarrely asymetrical arrangement?
If it's not simply an oversight, ...
I think it is almost certainly an oversight that readv() isn't listed
in the table in XSH 2.4.3.

It is arguable that it *is* required to be async-signal-safe despite
not being listed there, since its description starts with "The readv()
function shall be equivalent to read(), except as described below",
and nothing "below" says that one of the exceptions is that the
async-signal-safe requirement for read() does not apply to readv().

Likewise for writev().
--
Geoff Clare <***@gclare.org.uk>
Geoff Clare
2021-03-02 14:24:03 UTC
Permalink
Post by Geoff Clare
I think it is almost certainly an oversight that readv() isn't listed
in the table in XSH 2.4.3.
I have submitted an Austin Group defect report to ask for readv() and
writev() to be added to the table.

https://austingroupbugs.net/view.php?id=1455
--
Geoff Clare <***@gclare.org.uk>
Rainer Weikusat
2021-03-02 15:12:44 UTC
Permalink
Post by Kaz Kylheku
Post by Rainer Weikusat
To my bewilderment, I just discovered that both read and recvmsg are
required to be async-signal safe but readv isn't
[...]
Post by Kaz Kylheku
The behavior is undefined if an unsafe function is interrupted by an
async signal handler which then calls an unsafe function, so what we
have to think about is how an interrupted and re-entered readv
could misbehave.
[...]

I don't think this should be applicable: Both recvmsg and sendmsg (I'm
really dealing with sockets and wanted to avoid handling a msghdr
structure for a receive operation using none of its extended features)
are required to be async-signal safe and they use scatter-gather-I/O,
too.
Kaz Kylheku
2021-03-02 16:05:14 UTC
Permalink
Post by Rainer Weikusat
Post by Kaz Kylheku
Post by Rainer Weikusat
To my bewilderment, I just discovered that both read and recvmsg are
required to be async-signal safe but readv isn't
[...]
Post by Kaz Kylheku
The behavior is undefined if an unsafe function is interrupted by an
async signal handler which then calls an unsafe function, so what we
have to think about is how an interrupted and re-entered readv
could misbehave.
[...]
I don't think this should be applicable: Both recvmsg and sendmsg (I'm
really dealing with sockets and wanted to avoid handling a msghdr
structure for a receive operation using none of its extended features)
are required to be async-signal safe and they use scatter-gather-I/O,
too.
Great point!

Loading...