Set the queue length in unix domain socket - Unix
This is a discussion on Set the queue length in unix domain socket - Unix ; Hi all,
I'm trying to implement IPC with Unix Domain Sockets. A producer
encodes live video frames, and passes them to a consumer through an
unix domain socket. The consumer waits on the file descriptor with a
select, and when ...
-
Set the queue length in unix domain socket
Hi all,
I'm trying to implement IPC with Unix Domain Sockets. A producer
encodes live video frames, and passes them to a consumer through an
unix domain socket. The consumer waits on the file descriptor with a
select, and when the select returns, it reads data from the socket
(please note I can't change this, because the consumer is a third-
party library).
I want my socket to be a SOCK_SEQPACKET, because I want to keep the
boundaries between the frames, and I want them to arrive in order at
the other end.
The producer starts way before the occasional consumer - it's part of
a server, and just sits there encoding frames and putting them on the
socket. When the consumer needs them, it checks if there's data with
select, reads from the socket and uses them.
The problem is, the producer starts to put frames into the socket
until it blocks because the socket's queue is full. The consumer then
randomly starts to read and gets a lot of data to compute, at least
until it manages to empty the socket queue. This makes the application
lag and causes other unwanted behaviours that I don't explain because
they're related to the third party library.
What I want from my producer is to produce a frame, put it in the
socket, then produce another and get blocked on the write until the
first is consumed. I know I can set the maximum buffer size of the
socket with SO_SNDBUF, but unfortunately the frames are not fixed-
length.
What I'd need would be a way to limit the "datagram queue" of the
socket to one datagram, so that the producer would write the first
frame, get another and block on the write() until that frame has been
read by the consumer (removed from the queue). Then, it would complete
the write, get another live frame and write it into the socket, and so
on.
Is it possible to do something like that under Linux and for a single
UD socket (I don't want to change the value system wide)? If not, how
would you do it?
Please note that:
- I want to use datagram unix domain sockets because they preserve
boundaries and I can read one frame at a time. I *can't* buffer on the
other side.
- Frames are not fixed-length. One frame could be long 19 bytes,
another 15 Kb or more.
- I've got to use a socket because I need to pass an file descriptor
to the library consumer. The library will sit on a select() until
there's something ready on the socket.
- No, I can't modify the library or use another (even if it's clearly
wack).
Thanks in advance,
Cristiano.
-
Re: Set the queue length in unix domain socket
Cristiano wrote:
> What I want from my producer is to produce a frame, put it in the
> socket, then produce another and get blocked on the write until the
> first is consumed. I know I can set the maximum buffer size of the
> socket with SO_SNDBUF, but unfortunately the frames are not fixed-
> length.
>
> What I'd need would be a way to limit the "datagram queue" of the
> socket to one datagram, so that the producer would write the first
> frame, get another and block on the write() until that frame has been
> read by the consumer (removed from the queue). Then, it would complete
> the write, get another live frame and write it into the socket, and so
> on.
>
> Is it possible to do something like that under Linux and for a single
> UD socket (I don't want to change the value system wide)? If not, how
> would you do it?
AFAIU, the system wide knob is /proc/sys/net/unix/max_dgram_qlen
http://www.linuxinsight.com/proc_sys...gram_qlen.html
I'm not sure how to achieve the same result on a per-socket basis.
-
Re: Set the queue length in unix domain socket
On 11 Mar, 10:17, Noob wrote:
> Cristiano wrote:
> > What I want from my producer is to produce a frame, put it in the
> > socket, then produce another and get blocked on the write until the
> > first is consumed. I know I can set the maximum buffer size of the
> > socket with SO_SNDBUF, but unfortunately the frames are not fixed-
> > length.
>
> > What I'd need would be a way to limit the "datagram queue" of the
> > socket to one datagram, so that the producer would write the first
> > frame, get another and block on the write() until that frame has been
> > read by the consumer (removed from the queue). Then, it would complete
> > the write, get another live frame and write it into the socket, and so
> > on.
>
> > Is it possible to do something like that under Linux and for a single
> > UD socket (I don't want to change the value system wide)? If not, how
> > would you do it?
>
> AFAIU, the system wide knob is /proc/sys/net/unix/max_dgram_qlen
>
> http://www.linuxinsight.com/proc_sys...gram_qlen.html
>
> I'm not sure how to achieve the same result on a per-socket basis.
Alternatively, how to flush the socket's outgoing queue? When my
thread is stopped it already had the time to enqueue several unwanted
datagrams on the socket. When I stop it, I'd want it to simply clear
its outgoing queue so that it restarts with a brand new frame the next
time it's restarted.
-
Re: Set the queue length in unix domain socket
Cristiano wrote:
> Alternatively, how to flush the socket's outgoing queue? When my
> thread is stopped it already had the time to enqueue several unwanted
> datagrams on the socket. When I stop it, I'd want it to simply clear
> its outgoing queue so that it restarts with a brand new frame the next
> time it's restarted.
I've asked this question in the past, and I was told that the sockets
API does not provide a function to do this.
So I use (roughly) the following logic.
void flush_socket(int sock)
{
while ( 1 )
{
ssize_t res = recv(sock, NULL, 0, MSG_DONTWAIT);
if (res < 0) break;
}
}
Calling flush_socket() costs one system call per datagram in
the receive buffer, but nothing is copied.
Regards.
-
Re: Set the queue length in unix domain socket
On 12 Mar, 09:56, Noob wrote:
> Cristiano wrote:
> > Alternatively, how to flush the socket's outgoing queue? When my
> > thread is stopped it already had the time to enqueue several unwanted
> > datagrams on the socket. When I stop it, I'd want it to simply clear
> > its outgoing queue so that it restarts with a brand new frame the next
> > time it's restarted.
>
> I've asked this question in the past, and I was told that the sockets
> API does not provide a function to do this.
>
> So I use (roughly) the following logic.
>
> void flush_socket(int sock)
> {
> while ( 1 )
> {
> ssize_t res = recv(sock, NULL, 0, MSG_DONTWAIT);
> if (res < 0) break;
> }
>
> }
>
> Calling flush_socket() costs one system call per datagram in
> the receive buffer, but nothing is copied.
>
> Regards.
The consumer will have to do this, of course. Seems it could work,
many thanks.
Anyway, it's a pity one just can't set the socket queue length on a
per-socket basis or simply flush its queue 
Regards,
Cristiano.