Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 3 Nov 2020 18:35:34 -0500
From:      =?UTF-8?Q?J=C3=A9r=C3=A9mie_Galarneau?= <jeremie.galarneau@efficios.com>
To:        freebsd-hackers@freebsd.org
Cc:        Michael Jeanson <mjeanson@efficios.com>
Subject:   poll() POLLHUP behaviour inconsistency
Message-ID:  <CA%2BjJMxuBj7EsZ76zg%2B9_bjm46N50%2BF7UG7yGt4zXy0q3VZbGng@mail.gmail.com>

next in thread | raw e-mail | index | archive | help
Hi,

Michael and myself are porting code from Linux to FreeBSD and we have notic=
ed a
peculiar difference in the way poll() events are handled.

In short, we have a process that monitors the lifetime of other processes. =
It
does so by sharing a pipe between the parent and the child on every fork:
read-end in the parent, write-end in the child. The pipe is not used to
communicate; it's only used to poll() on the death of the child process.

On Linux, poll() is called with a POLLHUP event and nothing else. When
the child process dies, the poll() call returns with 'revents =3D=3D POLLHU=
P'.

After some head scratching, we figured that on FreeBSD (12.1 and 12.2) if t=
he
child process died while the parent was not waiting in poll(), we would get
'revents =3D=3D POLLHUP' on the next invocation of poll(), like we do on Li=
nux.
However, if the parent is in poll() when the child dies, the call to poll()
never unblocks. This resulted in occasional hangs in the application.

I am joining a reproducer [1].


As indicated, changing the 'events' to 'POLLIN | POLLHUP' causes both event=
s to
be delivered in both cases (child dies before/during calling poll()).

The following excerpts of the FreeBSD, Linux, and Open Specification seem
in agreement that passing POLLHUP is unnecessary as it is checked implicitl=
y.

FreeBSD (POLL(2))
  This flag is always checked, even if not present in the events bitmask [.=
..]

Open Group:
  This flag is only valid in the revents bitmask; it shall be ignored in th=
e
  events member.

Linux (poll(2)):
  Hang up (only  returned  in revents; ignored in events).


I am surprised by the behaviour being different depending on the moment the
child process' death occurs.

This is not a big deal for us to work-around, but I would like to know if I
should open a bug and try to fix it or if this is intentional (and perhaps
documented?) behaviour.

Thanks!
J=C3=A9r=C3=A9mie Galarneau

[1] https://gist.github.com/jgalar/5c3c2673b69fa0df652bda80a88f860c

--=20
J=C3=A9r=C3=A9mie Galarneau
EfficiOS Inc.
http://www.efficios.com



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?CA%2BjJMxuBj7EsZ76zg%2B9_bjm46N50%2BF7UG7yGt4zXy0q3VZbGng>