poll
API compatibility for Darwin
Many software packages use the poll
API instead of the select
API to
determine when file descriptors are ready for reading and/or writing etc.
Unfortunately on the "Darwin" platform the poll
API man page contains this
little tidbit:
BUGS
The poll() system call currently does not support devices.
To elaborate on that a bit, if the file descriptor is a character device such
as isatty
or a serial port device (perhaps via a third party add-on) the
poll
system call must not be used or incorrect results will ensue.
To check for the problem using LibreSSL, execute this test command:
openssl s_client -connect 8.8.8.8:443 </dev/null >/dev/null
Output should be less than a dozen lines of text with the last line being
exactly DONE
and nothing else. If the last line is poll error
instead then
this pollcompat workaround will be needed for correct operation. Feel free to
replace the 8.8.8.8
in the test command with the name or address of your
favorite SSL/TLS server (that's listening on port 443) instead.
A small wrapper pollcompat
function is provided that has an identical API
to the poll
function except that it works on devices by redirecting the
function call to select
. Compiling with -Dpoll=pollcompat
and then linking
with the pollcompat.o
object file supplies the necessary functionality.
By default, if all passed file descriptors are valid, open and !isatty
then
the standard system poll
function is used. However, building pollcompat.o
with the -DPOLLCOMPAT_ALWAYS
option will prevent the system poll
function
from ever being used.
By default, any file descriptors with a value greater than or equal to
1024 (FD_SETSIZE) will result in an error unless the system poll
function
ended up being used to implement the call. Building pollcompat.o
with the
-DPOLLCOMPAT_UNLIMITED
option will allow file descriptors up to a value of
10239 (OPEN_MAX - 1) to be used (Darwin never supports more than 10240 file
descriptors) but each pollcompat
call that uses file descriptors with a value
larger than 1023 will result in a pair of calloc/free calls.
The following settings:
CPPFLAGS='-DIPV6_TCLASS=36 -Dpoll=pollcompat' LIBS="-L$PWD -lpollcompat"
are sufficient when running the LibreSSL configure
script provided that the
pollcompat.c
source file has already been compiled with something like this:
cc -c -o pollcompat.o -O2 pollcompat.c
ar cru libpollcompat.a pollcompat.o
ranlib libpollcompat.a
(The -DIPV6_TCLASS=36
part can be omitted when building for Mac OS X 10.6 or
later and only affects building the netcat nc
binary.)
A LibreSSL built this way passes all tests and both of the resulting nc
and
openssl
binaries are fully operational when talking to a tty on standard
input (i.e. nc localhost 80
or openssl s_client -connect localhost:443
).