Руби 1.8.7. Я вызываю чтение для сокета, который был открыт и связан с:
socket = Socket.new(AF_INET, SOCK_STREAM, 0)
sockaddr = Socket.sockaddr_in(mp.port, mp.ip_address.ip)
begin
socket.connect_nonblock(sockaddr)
[...]
Соединение подтверждается вызовом select() и последующим подключением во второй раз в поисках Errno::EISCONN.
Затем я снова вызываю select с тайм-аутом 0, и если возврат не равен нулю, я читаю из сокета, сначала подтверждая, что он имеет установленный O_NONBLOCK:
rc = select([socket], nil, nil, 0)
puts " select returned: #{rc.pretty_inspect}"
if rc
begin
puts " reading: #{socket} nonblock: #{socket.fcntl(Fcntl::F_GETFL) & Fcntl::O_NONBLOCK}"
response = socket.read
puts " done reading"
[...]
Все это происходит в цикле один раз в минуту. Вывод в первый раз через цикл:
select returned: [[#<Socket:0xb6e0dcb8>], [], []]
reading: #<Socket:0xb6e0dcb8> nonblock: 2048
done reading
Однако второй раз через цикл зависает здесь:
select returned: [[#<Socket:0xb6e0dcb8>], [], []]
reading: #<Socket:0xb6e0dcb8> nonblock: 2048
Присоединение gdb к процессу показывает следующую трассировку:
0 0xffffe410 в __kernel_vsyscall()
1 0xb7e5539d в select() из /lib/tls/i686/cmov/libc.so.6
2 0x08064368 в rb_thread_schedule() at eval.c:11020
3 0x080785bb в io_fread(
Замена вызова read вызовом rcvfrom_nonblock работает, и, что интересно, он не получает EAGAIN, он фактически читает данные (как и следовало ожидать, учитывая возврат от select).
Любые идеи?
Стив
mp
устанавливается послеselect(2)
. Вы уверены, что он индексирует тот же сокет, который был доступен для чтения? - person Nikolai Fetissov   schedule 19.10.2010gdb
, это похоже на гонку в самом интерпретаторе Ruby. - person Nikolai Fetissov   schedule 20.10.2010