0

Suppose we have a file descriptor for a TCP socket. Is there a way to poll for data written to a socket (as opposed to data being available for reading, or the socket being available for writing)? i.e. if using poll, it would cause poll to wake up whenever somebody writes to that file descriptor?

In other words, say Thread A waits a while and then decides to write data to fd (perhaps after it has also ensured that POLLOUT is true). Is there a way for Thread B to discover that something has written to this file descriptor just now, without Thread A doing anything besides using normal system calls (and not signalling Thread B in any particular way) and in a blocking manner? (For example, one could monitor the TCP connection in a busy loop to see if more data has been written to the kernel buffers - but not what I'm talking about here).

The events available with poll seem to imply it's not possible with this function, but wondering if there's another way to do this or not. Is this possible in userspace (without mucking around in the kernel)?

7
  • 4
    No it's not possible. But what is the underlying problem that you think would be solve by knowing when some other entity (process, thread, etc.) writes to the descriptor? Perhaps if you ask about that underlying and actual problem directly, we might be able to help you with that. In its current state, your question is an XY problem. Commented Apr 17, 2024 at 13:13
  • @Someprogrammerdude The idea would be to have another thread that can monitor data written to a file descriptor, without modifying the rest of the program. This could be achieved by constantly looping as I mentioned, but I was looking for a blocking solution for efficiency reasons. Alternately, the rest of the program would need to be modified. Commented Apr 17, 2024 at 13:19
  • One approach might be to make a socketpair and give the writing thread one of the two sockets to write to instead of the original socket. Then the written data will arrive on the other socket, where your thread can react to it and then forward the data on to the original TCP socket. Commented Apr 17, 2024 at 13:24
  • As a possible work-around, use a pipe instead of the socket directly. Then thread B writes to the pipe, and thread A reads from it and passes it on to the actual socket (kind of like a proxy). I don't think it's a good solution, and I still don't understand your reason for needing this (why do you need to monitor the data that is written?), but it could be a way around the limitation. Commented Apr 17, 2024 at 13:24
  • 1
    @Someprogrammerdude Yeah, in fact, that's my current approach, is adding some APIs that should be used instead, I was thinking it would be more elegant though if that wasn't needed. I don't actually care about the data itself, I just want to be able to monitor some of the kernel TCP properties while writes are happening, which is why being able to have a thread "wake up" when something is being written to the socket would be sufficient. A pipe is unidirectional so would break the application's socket abstraction; another socket works but requires relaying in the other thread Commented Apr 17, 2024 at 13:33

1 Answer 1

2

Assuming Linux, I don't see an immediate satisfactory answer, but can suggest a few potential approaches:

  1. use ioctl() to continuously monitor TIOCOUTQ on the TCP socket being used by Thread A. Not very elegant (or deterministic) and possibly the type of busy loop approach you had hoped to avoid. If you wanted that "watcher" loop to wake up an arbitrary poll instance elsewhere, it could easily write to an eventfd and you could block on that separately.

  2. intercept the outbound socket writes with some sort of wrapper API applied at Thread A. Same concept as others have suggested above, but you might also consider whether async I/O wrappers might do the trick here (with AIO completion/error notifications ending up at Thread B ?).

  3. use an LD_PRELOAD library to intercept the syscalls that Thread A is using. Under the hood your hijacked versions of send or write would have to employ getsockopt() with SO_PROTOCOL/SO_DOMAIN to be sure you were only affecting socket descriptors of interest, and then you have to relay an appropriate notification to Thread B with some other IPC mechanism.

All in all, it sounds as though your current approach might be the most robust, and it that scenario I'd be inclined to say IIABDFI.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.