public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
* [bug] af_unix: Reading from a stream socket may lock the concurrent poll() call
@ 2011-11-20 20:19 Alexey Moiseytsev
  2011-11-20 20:31 ` David Miller
  2011-11-21 14:38 ` Eric Dumazet
  0 siblings, 2 replies; 5+ messages in thread
From: Alexey Moiseytsev @ 2011-11-20 20:19 UTC (permalink / raw)
  To: linux-kernel; +Cc: netdev, mtk.manpages, linux-man

Hello,

The following program shows how the poll() call hangs on a non-empty
stream socket.

#include <sys/types.h>
#include <sys/socket.h>
#include <pthread.h>
#include <stdio.h>
#include <unistd.h>
#include <poll.h>

int sockets[2];

int poll_socket(void) {
    struct pollfd pfd = {
        .fd = sockets[1],
        .events = POLLIN
    };
    return poll(&pfd, 1, -1);
}


/* observer routine doesn't modify amount of data available in the
socket buffer */
void* observer(void* arg) {
    char buffer;
    for (int j = 0; j < 2000; j++) {
        recv(sockets[1], &buffer, sizeof(buffer), MSG_PEEK);
        sched_yield();
    }
    return NULL;
}

int main(void) {
    if (socketpair(PF_UNIX, SOCK_STREAM, 0, sockets) == -1)
        return 1;
    int rc, data[250] = {0};
    if ((rc = send(sockets[0], &data, sizeof(data), MSG_DONTWAIT)) <= 0)
        return 2;
    poll_socket();
/* If the first poll_socket() call didn't hang then the following
message will be printed */
    fprintf(stderr, "%d bytes available in input buffer\n", rc);
    pthread_t observer_thread;
    pthread_create(&observer_thread, NULL, observer, NULL);
    for (int j = 0; j < 20000; j++) {
/* If the first poll_socket() call didn't hang then all the following
calls should do the same */
        poll_socket();
    }
    fprintf(stderr, "Well done\n");
    pthread_join(observer_thread, NULL);
    close(sockets[0]);
    close(sockets[1]);
    return 0;
}


Expected output: two lines or nothing (in case of error).
Observed output: only the first line (and the process never exits).

So the first poll() said that there is some data available in the
socket. And one of the following poll() said that there is no data
available in the socket. But this is false because the observer thread
didn't actually consume any data from then socket.

I assume that this bug can be eliminated by adding
sk->sk_data_ready(...) call right after each call to
skb_queue_head(..) in the unix_stream_recvmsg(...) routine
(net/unix/af_unix.c)

Other info:
$ uname -srmo
Linux 2.6.32-5-amd64 x86_64 GNU/Linux

-- 
Alexey

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [bug] af_unix: Reading from a stream socket may lock the concurrent poll() call
  2011-11-20 20:19 [bug] af_unix: Reading from a stream socket may lock the concurrent poll() call Alexey Moiseytsev
@ 2011-11-20 20:31 ` David Miller
  2011-11-21 23:34   ` Alexey Moiseytsev
  2011-11-21 14:38 ` Eric Dumazet
  1 sibling, 1 reply; 5+ messages in thread
From: David Miller @ 2011-11-20 20:31 UTC (permalink / raw)
  To: himeraster; +Cc: linux-kernel, netdev, mtk.manpages, linux-man

From: Alexey Moiseytsev <himeraster@gmail.com>
Date: Mon, 21 Nov 2011 00:19:02 +0400

> Other info:
> $ uname -srmo
> Linux 2.6.32-5-amd64 x86_64 GNU/Linux

There have been numerous AF_UNIX bug fixes since that release, please try
to reproduce your problem with current kernels.

Thanks.

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [bug] af_unix: Reading from a stream socket may lock the concurrent poll() call
  2011-11-20 20:19 [bug] af_unix: Reading from a stream socket may lock the concurrent poll() call Alexey Moiseytsev
  2011-11-20 20:31 ` David Miller
@ 2011-11-21 14:38 ` Eric Dumazet
  2011-11-21 23:34   ` Alexey Moiseytsev
  1 sibling, 1 reply; 5+ messages in thread
From: Eric Dumazet @ 2011-11-21 14:38 UTC (permalink / raw)
  To: Alexey Moiseytsev; +Cc: linux-kernel, netdev, mtk.manpages, linux-man

Le lundi 21 novembre 2011 à 00:19 +0400, Alexey Moiseytsev a écrit :
> Hello,
> 
> The following program shows how the poll() call hangs on a non-empty
> stream socket.
> 
> #include <sys/types.h>
> #include <sys/socket.h>
> #include <pthread.h>
> #include <stdio.h>
> #include <unistd.h>
> #include <poll.h>
> 
> int sockets[2];
> 
> int poll_socket(void) {
>     struct pollfd pfd = {
>         .fd = sockets[1],
>         .events = POLLIN
>     };
>     return poll(&pfd, 1, -1);
> }
> 
> 
> /* observer routine doesn't modify amount of data available in the
> socket buffer */
> void* observer(void* arg) {
>     char buffer;
>     for (int j = 0; j < 2000; j++) {
>         recv(sockets[1], &buffer, sizeof(buffer), MSG_PEEK);
>         sched_yield();
>     }
>     return NULL;
> }
> 
> int main(void) {
>     if (socketpair(PF_UNIX, SOCK_STREAM, 0, sockets) == -1)
>         return 1;
>     int rc, data[250] = {0};
>     if ((rc = send(sockets[0], &data, sizeof(data), MSG_DONTWAIT)) <= 0)
>         return 2;
>     poll_socket();
> /* If the first poll_socket() call didn't hang then the following
> message will be printed */
>     fprintf(stderr, "%d bytes available in input buffer\n", rc);
>     pthread_t observer_thread;
>     pthread_create(&observer_thread, NULL, observer, NULL);
>     for (int j = 0; j < 20000; j++) {
> /* If the first poll_socket() call didn't hang then all the following
> calls should do the same */
>         poll_socket();
>     }
>     fprintf(stderr, "Well done\n");
>     pthread_join(observer_thread, NULL);
>     close(sockets[0]);
>     close(sockets[1]);
>     return 0;
> }
> 
> 
> Expected output: two lines or nothing (in case of error).
> Observed output: only the first line (and the process never exits).
> 
> So the first poll() said that there is some data available in the
> socket. And one of the following poll() said that there is no data
> available in the socket. But this is false because the observer thread
> didn't actually consume any data from then socket.
> 
> I assume that this bug can be eliminated by adding
> sk->sk_data_ready(...) call right after each call to
> skb_queue_head(..) in the unix_stream_recvmsg(...) routine
> (net/unix/af_unix.c)
> 
> Other info:
> $ uname -srmo
> Linux 2.6.32-5-amd64 x86_64 GNU/Linux
> 

Hi Alexy

I believe you found a bug and your suggested fix should be just fine.

(Or maybe testing in unix_poll() that at least one thread is currently
handling one skb from sk->receive_queue)

Could you submit an official patch on top of current Linus tree or do
you prefer us to take care of this ?




^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [bug] af_unix: Reading from a stream socket may lock the concurrent poll() call
  2011-11-20 20:31 ` David Miller
@ 2011-11-21 23:34   ` Alexey Moiseytsev
  0 siblings, 0 replies; 5+ messages in thread
From: Alexey Moiseytsev @ 2011-11-21 23:34 UTC (permalink / raw)
  To: David Miller; +Cc: linux-kernel, netdev

21.11.2011 00:31, David Miller пишет:
> From: Alexey Moiseytsev<himeraster@gmail.com>
> Date: Mon, 21 Nov 2011 00:19:02 +0400
>
>> Other info:
>> $ uname -srmo
>> Linux 2.6.32-5-amd64 x86_64 GNU/Linux
>
> There have been numerous AF_UNIX bug fixes since that release, please try
> to reproduce your problem with current kernels.
>

I upgraded kernel up to 3.2-rc2 but the problem still exists.

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [bug] af_unix: Reading from a stream socket may lock the concurrent poll() call
  2011-11-21 14:38 ` Eric Dumazet
@ 2011-11-21 23:34   ` Alexey Moiseytsev
  0 siblings, 0 replies; 5+ messages in thread
From: Alexey Moiseytsev @ 2011-11-21 23:34 UTC (permalink / raw)
  To: Eric Dumazet; +Cc: linux-kernel, netdev

21.11.2011 18:38, Eric Dumazet пишет:
> Le lundi 21 novembre 2011 à 00:19 +0400, Alexey Moiseytsev a écrit :
>> Hello,
>>
>> The following program shows how the poll() call hangs on a non-empty
>> stream socket.
>>
>> #include<sys/types.h>
>> #include<sys/socket.h>
>> #include<pthread.h>
>> #include<stdio.h>
>> #include<unistd.h>
>> #include<poll.h>
>>
>> int sockets[2];
>>
>> int poll_socket(void) {
>>      struct pollfd pfd = {
>>          .fd = sockets[1],
>>          .events = POLLIN
>>      };
>>      return poll(&pfd, 1, -1);
>> }
>>
>>
>> /* observer routine doesn't modify amount of data available in the
>> socket buffer */
>> void* observer(void* arg) {
>>      char buffer;
>>      for (int j = 0; j<  2000; j++) {
>>          recv(sockets[1],&buffer, sizeof(buffer), MSG_PEEK);
>>          sched_yield();
>>      }
>>      return NULL;
>> }
>>
>> int main(void) {
>>      if (socketpair(PF_UNIX, SOCK_STREAM, 0, sockets) == -1)
>>          return 1;
>>      int rc, data[250] = {0};
>>      if ((rc = send(sockets[0],&data, sizeof(data), MSG_DONTWAIT))<= 0)
>>          return 2;
>>      poll_socket();
>> /* If the first poll_socket() call didn't hang then the following
>> message will be printed */
>>      fprintf(stderr, "%d bytes available in input buffer\n", rc);
>>      pthread_t observer_thread;
>>      pthread_create(&observer_thread, NULL, observer, NULL);
>>      for (int j = 0; j<  20000; j++) {
>> /* If the first poll_socket() call didn't hang then all the following
>> calls should do the same */
>>          poll_socket();
>>      }
>>      fprintf(stderr, "Well done\n");
>>      pthread_join(observer_thread, NULL);
>>      close(sockets[0]);
>>      close(sockets[1]);
>>      return 0;
>> }
>>
>>
>> Expected output: two lines or nothing (in case of error).
>> Observed output: only the first line (and the process never exits).
>>
>> So the first poll() said that there is some data available in the
>> socket. And one of the following poll() said that there is no data
>> available in the socket. But this is false because the observer thread
>> didn't actually consume any data from then socket.
>>
>> I assume that this bug can be eliminated by adding
>> sk->sk_data_ready(...) call right after each call to
>> skb_queue_head(..) in the unix_stream_recvmsg(...) routine
>> (net/unix/af_unix.c)
>>
>> Other info:
>> $ uname -srmo
>> Linux 2.6.32-5-amd64 x86_64 GNU/Linux
>>
>
> Hi Alexy
>
> I believe you found a bug and your suggested fix should be just fine.
>
> (Or maybe testing in unix_poll() that at least one thread is currently
> handling one skb from sk->receive_queue)
>
> Could you submit an official patch on top of current Linus tree or do
> you prefer us to take care of this ?
>

Hi,

I will try to send a patch. If I will do something wrong, feel free to 
submit it yourself.

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2011-11-21 23:34 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2011-11-20 20:19 [bug] af_unix: Reading from a stream socket may lock the concurrent poll() call Alexey Moiseytsev
2011-11-20 20:31 ` David Miller
2011-11-21 23:34   ` Alexey Moiseytsev
2011-11-21 14:38 ` Eric Dumazet
2011-11-21 23:34   ` Alexey Moiseytsev

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox