The why is just the way it works, by design.
In the kernel, calling recv() called fget() on the struct file corresponding to the file descriptor, and this will prevent it from being freed up to the corresponding fput() .
You just need to change your design (your design is inherently very large), since this will happen, you should not block the file descriptor protection in user space, which means that close() could happen just before recv() call - and the file descriptor was even reused for something else).
If you want to wake up another stream that blocks the file descriptor, you must block it on select() , as well as in the handset included in the set of file descriptors that can be written to the main stream.
source share