Рубин 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, и если возвращаемое значение не равно nil, я читаю из сокета, сначала подтверждая, что для него установлено 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 () на eval.c: 11020
3 0x080785bb в io_fread (
Замена вызова read на вызов rcvfrom_nonblock работает, и, что интересно, он не получает EAGAIN, он фактически читает данные (как и следовало ожидать, учитывая возврат из select).
Есть идеи?
стив