Select does *not* tell you if a file descriptor is writeable or readable.
It tells you if the read/write operation will block.
This is something subtly different.
This is interesting for blocking mode.
But since you can switch to nonblocking mode every operation will return immediately.
Here are some descriptions I found about select:
http://publib.boulder.ibm.com/infocenter/tpfhelp/current/index.jsp?topic=/com.ibm.ztpf-ztpfdf.doc_put.cur/gtpc2/cpp_select.html http://docs.sun.com/app/docs/doc/816-5168/select-3c?a=view http://www.developerweb.net/forum/showthread.php?p=13486
"...The select socket function monitors a list of file descriptors for readability, readiness for writing, and exception pending conditions."
Of course if you are in a blocking mode then a call does not block. ...if the select call returns that what we expect.
Show quoted text 10 lines
For instance, it reports file descriptor 0 as writable, which is rather
strange, since it
is read-only, but correct, because the write call will not block. Indeed the
write call
will return at once with an error condition.
This is what the kernel sees (I used strace to test your code with descriptor
0):
select(1, NULL, [0], NULL, {0, 0}) = 1 (out [0], left {0, 0})
May be it is better to test it with sockets descriptors. If I get a result that the call will not block (as you say) and then I write data to the descriptor then the program crashes with exitcode 13...
Which is exactly what I sent.
In short, is_writable_socket should be implemented differently, not using
select.
How can I find out if a socket connection in a nonblocking mode is established?
Michael.
dmitry boyarintsev wrotehello Rainer,
do you check the socket's writability by fpFD_ISSET(sck, fds) ?
Yes, before I did it this way, but it was the same behaviour. Windows ok. Linux failed.
function is_writable_socket2( s : integer ; var error : longint ) : boolean;
var
fds : tfdset;
tv : timeval;
valopt : longint = 1;
vallen : {$ifdef linux} longword {$else} longint {$endif};
begin
result := false;
{$ifdef linux} fpfd_zero( fds ); fpfd_set( s , fds ); {$endif}
{$ifdef windows} fd_zero( fds ); fd_set( s , fds ); {$endif}
tv.tv_sec := 0;
tv.tv_usec := 0;
// socket+1 , read , write , except , timeout
{$ifdef linux}
if fpselect( s + 1 , nil , @fds , nil , @tv ) > 0 then begin
if fpfd_isset( s , fds ) = 1 then begin
vallen := sizeof( valopt );
if fpgetsockopt( s , sol_socket , so_error , @valopt , @vallen ) = 0
then begin
error := valopt;
result := valopt = 0;
end;
end;
end;
{$else}
if select( s + 1 , nil , @fds , nil , @tv ) > 0 then begin
if fd_isset( s , fds ) then begin
vallen := sizeof( valopt );
if getsockopt( s , sol_socket , so_error , valopt , vallen ) = 0 then
begin
error := valopt;
result := valopt = 0;
end;
end;
end;
{$endif}
end;
Show quoted text 5 lines
Rainer