mirror of
https://github.com/moparisthebest/curl
synced 2024-08-13 17:03:50 -04:00
Handle EAGAIN/EWOULDBLOCK readiness errors, which can occur for both TCP and
UDP even when a poll(2) or select(2) suggest otherwise.
This commit is contained in:
parent
55d22ba10c
commit
4524618bf2
@ -1,5 +1,13 @@
|
|||||||
Changelog for the c-ares project
|
Changelog for the c-ares project
|
||||||
|
|
||||||
|
* June 18, 2006
|
||||||
|
|
||||||
|
- William Ahern handles EAGAIN/EWOULDBLOCK errors in most of the I/O calls
|
||||||
|
from area_process.c.
|
||||||
|
|
||||||
|
TODO: Handle one last EAGAIN for a UDP socket send(2) in
|
||||||
|
ares__send_query().
|
||||||
|
|
||||||
* May 10, 2006
|
* May 10, 2006
|
||||||
|
|
||||||
- Bram Matthys brought my attention to a libtool peculiarity where detecting
|
- Bram Matthys brought my attention to a libtool peculiarity where detecting
|
||||||
|
@ -63,6 +63,7 @@
|
|||||||
#define GET_ERRNO() errno
|
#define GET_ERRNO() errno
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
static int try_again(int errnum);
|
||||||
static void write_tcp_data(ares_channel channel, fd_set *write_fds,
|
static void write_tcp_data(ares_channel channel, fd_set *write_fds,
|
||||||
time_t now);
|
time_t now);
|
||||||
static void read_tcp_data(ares_channel channel, fd_set *read_fds, time_t now);
|
static void read_tcp_data(ares_channel channel, fd_set *read_fds, time_t now);
|
||||||
@ -94,6 +95,31 @@ void ares_process(ares_channel channel, fd_set *read_fds, fd_set *write_fds)
|
|||||||
process_timeouts(channel, now);
|
process_timeouts(channel, now);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Return 1 if the specified errno describes a readiness error, or 0
|
||||||
|
* otherwise. This is mostly for HP-UX, which could return EAGAIN or
|
||||||
|
* EWOULDBLOCK. See this man page
|
||||||
|
*
|
||||||
|
* http://devrsrc1.external.hp.com/STKS/cgi-bin/man2html?manpage=/usr/share/man/man2.Z/send.2
|
||||||
|
*/
|
||||||
|
static int try_again(int errnum)
|
||||||
|
{
|
||||||
|
#if !defined EWOULDBLOCK && !defined EAGAIN
|
||||||
|
#error "Neither EWOULDBLOCK nor EAGAIN defined"
|
||||||
|
#endif
|
||||||
|
switch (errnum)
|
||||||
|
{
|
||||||
|
#ifdef EWOULDBLOCK
|
||||||
|
case EWOULDBLOCK:
|
||||||
|
return 1;
|
||||||
|
#endif
|
||||||
|
#if defined EAGAIN && EAGAIN != EWOULDBLOCK
|
||||||
|
case EAGAIN:
|
||||||
|
return 1;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/* If any TCP sockets select true for writing, write out queued data
|
/* If any TCP sockets select true for writing, write out queued data
|
||||||
* we have for them.
|
* we have for them.
|
||||||
*/
|
*/
|
||||||
@ -136,6 +162,7 @@ static void write_tcp_data(ares_channel channel, fd_set *write_fds, time_t now)
|
|||||||
free(vec);
|
free(vec);
|
||||||
if (wcount < 0)
|
if (wcount < 0)
|
||||||
{
|
{
|
||||||
|
if (!try_again(GET_ERRNO()))
|
||||||
handle_error(channel, i, now);
|
handle_error(channel, i, now);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -173,6 +200,7 @@ static void write_tcp_data(ares_channel channel, fd_set *write_fds, time_t now)
|
|||||||
|
|
||||||
if (scount < 0)
|
if (scount < 0)
|
||||||
{
|
{
|
||||||
|
if (!try_again(GET_ERRNO()))
|
||||||
handle_error(channel, i, now);
|
handle_error(channel, i, now);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -224,6 +252,7 @@ static void read_tcp_data(ares_channel channel, fd_set *read_fds, time_t now)
|
|||||||
2 - server->tcp_lenbuf_pos, 0);
|
2 - server->tcp_lenbuf_pos, 0);
|
||||||
if (count <= 0)
|
if (count <= 0)
|
||||||
{
|
{
|
||||||
|
if (!(count == -1 && try_again(GET_ERRNO())))
|
||||||
handle_error(channel, i, now);
|
handle_error(channel, i, now);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -250,6 +279,7 @@ static void read_tcp_data(ares_channel channel, fd_set *read_fds, time_t now)
|
|||||||
server->tcp_length - server->tcp_buffer_pos, 0);
|
server->tcp_length - server->tcp_buffer_pos, 0);
|
||||||
if (count <= 0)
|
if (count <= 0)
|
||||||
{
|
{
|
||||||
|
if (!(count == -1 && try_again(GET_ERRNO())))
|
||||||
handle_error(channel, i, now);
|
handle_error(channel, i, now);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -289,7 +319,9 @@ static void read_udp_packets(ares_channel channel, fd_set *read_fds,
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
count = recv(server->udp_socket, (void *)buf, sizeof(buf), 0);
|
count = recv(server->udp_socket, (void *)buf, sizeof(buf), 0);
|
||||||
if (count <= 0)
|
if (count == -1 && try_again(GET_ERRNO()))
|
||||||
|
continue;
|
||||||
|
else if (count <= 0)
|
||||||
handle_error(channel, i, now);
|
handle_error(channel, i, now);
|
||||||
|
|
||||||
process_answer(channel, buf, count, i, 0, now);
|
process_answer(channel, buf, count, i, 0, now);
|
||||||
@ -479,6 +511,7 @@ void ares__send_query(ares_channel channel, struct query *query, time_t now)
|
|||||||
if (send(server->udp_socket, (void *)query->qbuf,
|
if (send(server->udp_socket, (void *)query->qbuf,
|
||||||
query->qlen, 0) == -1)
|
query->qlen, 0) == -1)
|
||||||
{
|
{
|
||||||
|
/* FIXME: Handle EAGAIN here since it likely can happen. */
|
||||||
query->skip_server[query->server] = 1;
|
query->skip_server[query->server] = 1;
|
||||||
next_server(channel, query, now);
|
next_server(channel, query, now);
|
||||||
return;
|
return;
|
||||||
|
Loading…
Reference in New Issue
Block a user