There is a file socket descriptor (socketpair or pipe - no difference). It is required that it be blocked on read() in one process, but not in the other (that is, if there is no data, read() returns -1 and errno == EAGAIN ).

The fact is that

 int newfd = dup(oldfd); fcntl (newfd, F_SETFL, fcntl(newfd,F_GETFL)|O_NONBLOCK); 

Makes both descriptors unblockable . Calling fcntl() before fork() or after does not change the situation.

Similar behavior for both tty and regular file. It's easier with them (you can independently rediscover, for example, / dev / tty), but I'm interested in the socket (or pipe).

What are some ideas?

If you think that this is impossible in principle, also respond.

Perhaps the following information will be helpful:

Each file has its own flags, it has been flagged by open (2) and it can be modified by fcntl (). Duplicated file descriptors (made with dup (2), fcntl (F_DUPFD), fork (2), etc.).

IMHO from this it follows that I need somehow ( that's the point of the question ) to get a handle to a new record in the file table, referring to the same data queues as the specified socket.

PS

No doubt, but checked. execl() (system()) not affected.

  • I saw a similar use of descriptors with files only; there it rolls, since the same file can be opened several times and get several descriptors, but how to do the same with a socket seems to be bad due to the lack of a name. I can suggest trying to do the same thing, only with a call to dup2 () in the child process, then in theory there should be 2 different descriptors ... - margosh
  • Can it simply be redirected to a named pipe and already be dancing from it? - Ilya Pirogov
  • @margosh, dup () and dup2 () work the same way in this plan (dup3 will not work either). In general, the difference between fd = dup (old) and fd = dup2 (old, new) is that dup2 () closes new (if it was open) and returns a copy of old (i.e., fd) numerically equal to new, and dup () returns a copy of old without closing anything. The descriptors are different, of course, but the new descriptor will refer to the same system file table entry ( not the process! ) As the old one and share the same file status flags (of course, except for the FD_CLOEXEC flag, which is in the process descriptor table). - avp
  • @Ilya Pirogov, honestly, I do not understand how to do it. Do you propose to connect the socket descriptor with the open FIFO descriptor, then open the FIFO again and make this descriptor non-blocking? Here's how to connect the socket with the FIFO, explain in more detail, please. - avp
  • @avp, if so, then it makes no sense to use any of these functions. The situation you want to achieve would be called open () again for one file, but apparently this will not work with the socket. Tell me, why do you need to implement exactly this behavior? - margosh

1 answer 1

From the above quote it follows that each open file will have only its own descriptor (and it looks like one). And modifying from one place, we change in another.

In fact, the question is - why not use the blocking mode and call recv with the MSG_DONTWAIT parameter?

  • @KoVadim, good idea. Just change read to recv. "Scientific interest", of course, remained. And to practice the idea, then what you need. - avp
  • and if you look inside the recv documentation, you can find it there ... At one time, one flag in recv removed a bunch of code. Essence - on the first byte that came, it was necessary to determine which protocol the client came in (text, xml or ssl). The first byte uniquely identified the protocol. Initially, its own system of buffering and transferring the array into the libraries was built. Now - just reading 1 byte without removing it from the queue, analyzing, creating the necessary handler that receives the socket descriptor. - KoVadim
  • MSG_PEEK is a famous thing. Actually, in this case, I’m rather interested in some kind of protection for some processes, from changing O_NONBLOCK to others for a shared socket. - avp