Current-Users archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

Re: Partial reads on unix domain sockets



In article <m2y2dunwuf.fsf%thuvia.hamartun.priv.no@localhost>,
Tom Ivar Helbekkmo  <tih%hamartun.priv.no@localhost> wrote:
>Some time last year, probably late summer or autumn, a change was made
>that caused transfer of small chunks of data over unix domain sockets to
>have a higher chance of resulting in a read() getting only part of the
>chunk.
>
>While there is no guarantee of a one to one relationship between writes
>and reads, it seems that some applications expect this.  In my case, it
>was jack (pkgsrc/audio/jack) that failed.  It comes with, among other
>things, a daemon, jackd, and a library for use by clients wishing to
>connect to it.  Communication between jackd and its clients became
>impossible with this change, because the code in jack expects to be able
>to exchange C structs between server and clients.  The jackd server has
>a thread that uses poll() to wait for available packets from clients,
>and when something arrives, it is read with code like this example:
>
>   if (read (client_fd, &req, sizeof(req)) != sizeof(req)) {
>      jack_error ("cannot read ACK connection request from client");
>      return -1;
>   }
>
>The client_fd is an open unix domain stream socket, and it is *not* in
>non-blocking mode.  The structs being transfered are of various sizes,
>and can, from a casual inspection of the header files, be up to a couple
>of hundred bytes long.
>
>Data is written to the sockets using code like this:
>
>   if (write (reply_fd, &req, sizeof(req)) < (ssize_t)sizeof(req)) {
>      jack_error ("cannot write request result to client");
>      return -1;
>   }
>
>Meanwhile, in the client library, the code at the other end of this
>communication is simply:
>
>   if (write (fd, &req, sizeof(req)) != sizeof(req)) {
>      jack_error ("cannot write event connect request to server (%s)",
>                  strerror (errno));
>      close (fd);
>      return -1;
>   }
>
>   if (read (fd, &res, sizeof(res)) != sizeof(res)) {
>      jack_error ("cannot read event connect result from server (%s)",
>                  strerror (errno));
>      close (fd);
>      return -1;
>   }
>
>Obviously, poll() will return, with information about available data,
>before the entire chunk written by the other end is available.
>
>I haven't filed a PR on this, as it isn't technically an error in
>NetBSD.  However, if there is a wide-spread belief out there that code
>such as this will "just work" (I'm guessing it "just works" on Linux,
>just like it does on NetBSD < 10), and it's not otherwise detrimental to
>have the data from a single write() call all be available to the reader
>of the socket before triggering a select() or poll() that's waiting for
>it, then maybe such an adjustment should be considered.

Can you please file a PR with an example to keep track of it. It is a behavior
change after all and we should understand why it happened.

christos



Home | Main Index | Thread Index | Old Index