Perl IO :: Socket :: UNIX Connect с тайм-аутом дает EAGAIN / EWOULDBLOCK

Ubuntu Linux, ядро ​​2.6.32-45, 64b, Perl 5.10.1

Я подключаю к серверу много новых потоковых сокетов IO :: Socket :: UNIX, и в основном они работают нормально. Но иногда в многопоточной среде на более быстром процессоре они возвращают «Ресурс временно недоступен» (EAGAIN / EWOULDBLOCK). Я использую тайм-аут в Connect, поэтому сокеты переводятся в неблокирующий режим во время подключения. Но у меня период тайм-аута не наступает - он не ждет заметного времени, он быстро возвращается.

Я вижу, что внутри IO :: Socket он пытается подключиться, и если он терпит неудачу с EINPROGRESS или EAGAIN / EWOULDBLOCK, он делает выбор, чтобы дождаться установки бита записи. Пока это кажется нормальным. В моем случае выбор быстро выполняется, подразумевая, что бит записи установлен, а затем код пытается повторно подключиться. (Я предполагаю, что это попытка получить какую-либо ошибку из-за проскальзывания ошибки?) В любом случае повторное подключение снова не удается с EAGAIN / EWOULDBLOCK.

В моем коде это легко исправить с помощью цикла повторной попытки. Но я не понимаю, почему, когда сокет становится доступным для записи, он не может быть повторно подключен. Я думал, что select guard всегда достаточно для неблокирующего соединения. Очевидно нет; Итак, мои вопросы:

  • Какие условия приводят к сбою подключения при работе select (устанавливается бит записи)?
  • Есть ли лучший способ, чем вращение и повторная попытка, дождаться успешного подключения? Отжим тратит циклы. Вместо этого я бы хотел заблокировать что-то вроде выбора / опроса, но мне все равно нужен тайм-аут.

Спасибо,

- Стив


person user1873301    schedule 03.12.2012    source источник


Ответы (1)


Но я не понимаю, почему, когда сокет становится доступным для записи, он не может быть повторно подключен.

Я полагаю, это потому, что любой необходимый ресурс, который стал бесплатным, был схвачен, прежде чем вы смогли снова подключиться. Замена select на вращающуюся петлю не поможет.

person ikegami    schedule 03.12.2012
comment
Ага! Спасибо, ты заставил лампочку зажгнуться в моей голове. Я (ошибочно) думал, что первое соединение привело к тому, что все ресурсы были выделены и остались выделенными для сокета. Теперь я вижу, что ошибался в этом - статус EAGAIN (E-something) означает, что первое соединение было полностью выполнено и не удалось; второе соединение совершенно новое, полностью отличное от первого. Спасибо! - person user1873301; 04.12.2012