Close the socket using the shutdown()
call. This will wake up any threads blocked on it, while keeping the file descriptor valid.
close()
on a descriptor another thread B is using is inherently hazardous: another thread C may open a new file descriptor which thread B will then use instead of the closed one. dup2()
a /dev/null
onto it avoids that problem, but does not wake up blocked threads reliably.
Note that shutdown()
only works on sockets — for other kinds of descriptors you likely need the select+pipe-to-self or cancellation approaches.