Opened 6 years ago

Closed 6 years ago

#9734 closed bug (fixed)

Receiving from a nonblocking socket causes "Operation timed out" error

Reported by: markh Owned by: phoudoin
Priority: normal Milestone: R1
Component: Network & Internet/UDP Version: R1/Development
Keywords: Cc:
Blocked By: Blocking:
Has a Patch: no Platform: All

Description

When trying to receive data from a nonblocking socket, I get an "Operation timed out" error, while I am expecting a EWOULDBLOCK error as there is no data to read. Changing the socket to blocking does block as expected. I expanded my test case from #9678 and attached it to this ticket.

This happens with href45525.

Attachments (1)

socket_test_send_double_recv_1_socket.c (5.6 KB ) - added by markh 6 years ago.

Download all attachments as: .zip

Change History (6)

comment:1 by axeld, 6 years ago

The following code pieces are important here:

  1. How the kernel deals with timeouts
  2. The code calling it
  3. And the timeout computation

IOW either the code at 2.) must not use B_ABSOLUTE_TIMEOUT when the timeout is actually zero, or the kernel should treat absolute timeout as relative if the timeout is zero.

Opinions anyone? Maybe we should find out what BeOS did here, and stay compatible (which probably means changing 2.)).

comment:2 by phoudoin, 6 years ago

Except if BeOS handled a zero B_ABSOLUTE_TIMEOUT as a zero relative, which I doubt, I'm for fixing DatagramSocket template timeout handling.

I wonder why absolute timeout is used instead of relative one anyway?

in reply to:  2 ; comment:3 by bonefish, 6 years ago

Replying to phoudoin:

I wonder why absolute timeout is used instead of relative one anyway?

Usually it is necessary to convert relative timeouts to absolute ones, so that syscall aren't restarted with the full timeout each time. That might not be relevant here. Another reason (actually the same, just generalized) to convert to absolute is, if there are potentially multiple waits ahead.

I think the best way to do the timeout conversion is to always pass on a (bigtime_t, uint32) pair (make it a helper class, if you want something more handy to pass around). In the zero timeout case the conversion result would then be (0, B_RELATIVE_TIMEOUT) and the correct return code would be generated automatically. I would handle a 0 absolute timeout specially only if BeOS does. I don't have a BeOS installation at hand ATM, though.

An alternative for your case might be to check the return code and, if it is B_TIMED_OUT convert to B_WOULD_BLOCK, if the timeout is 0. Not that elegant, but IIRC other code does it the same way.

in reply to:  3 comment:4 by phoudoin, 6 years ago

Owner: changed from zooey to phoudoin
Status: newassigned

Replying to bonefish:

Usually it is necessary to convert relative timeouts to absolute ones, so that syscall aren't restarted with the full timeout each time. That might not be relevant here.

In fact, it is. Thanks for the explanation.

An alternative for your case might be to check the return code and, if it is B_TIMED_OUT convert to B_WOULD_BLOCK, if the timeout is 0. Not that elegant, but IIRC other code does it the same way.

I guess that the way to go, indeed. I'll do that, except if someone does it before.

comment:5 by axeld, 6 years ago

Resolution: fixed
Status: assignedclosed

Sorry, didn't notice you assigned it to yourself already! In any case, it's fixed in hrev45609 - I just use B_RELATIVE_TIMEOUT in case the timeout is 0.

Note: See TracTickets for help on using tickets.