2
0
mirror of https://gitlab.isc.org/isc-projects/bind9 synced 2025-08-31 06:25:31 +00:00

Add the socket flag ISC_R_NORETRY, which makes the socket code treat

a soft error as a hard error on send (that is, not retry it).  It also
modifies the code calling sendmsg() to retry on EINTR.
This commit is contained in:
Brian Wellington
2001-03-06 01:23:03 +00:00
parent f9e1aa0c44
commit 2eb3dafdcf
2 changed files with 56 additions and 31 deletions

View File

@@ -15,7 +15,7 @@
* WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/* $Id: socket.h,v 1.53 2001/02/12 21:43:17 bwelling Exp $ */
/* $Id: socket.h,v 1.54 2001/03/06 01:23:02 bwelling Exp $ */
#ifndef ISC_SOCKET_H
#define ISC_SOCKET_H 1
@@ -167,6 +167,7 @@ typedef enum {
* Flags for isc_socket_send() and isc_socket_recv() calls.
*/
#define ISC_SOCKFLAG_IMMEDIATE 0x00000001 /* send event only if needed */
#define ISC_SOCKFLAG_NORETRY 0x00000002 /* drop failed UDP sends */
/***
*** Socket and Socket Manager Functions
@@ -569,12 +570,20 @@ isc_socket_sendto2(isc_socket_t *sock, isc_region_t *region,
* expected to be initialized.
*
* For isc_socket_sendto2():
* The only defined value for 'flags' is ISC_SOCKFLAG_IMMEDIATE. If
* set and the operation completes, the return value will be
* ISC_R_SUCCESS and the event will be filled in and not sent. If the
* operation does not complete, the return value will be
* ISC_R_INPROGRESS and the event will be sent when the operation
* completes.
* The only defined values for 'flags' are ISC_SOCKFLAG_IMMEDIATE
* and ISC_SOCKFLAG_NORETRY.
*
* If ISC_SOCKFLAG_IMMEDIATE is set and the operation completes, the
* return value will be ISC_R_SUCCESS and the event will be filled
* in and not sent. If the operation does not complete, the return
* value will be ISC_R_INPROGRESS and the event will be sent when
* the operation completes.
*
* ISC_SOCKFLAG_NORETRY can only be set for UDP sockets. If set
* and the send operation fails due to a transient error, the send
* will not be retried and the error will be indicated in the event.
* Using this option along with ISC_SOCKFLAG_IMMEDIATE allows the caller
* to specify a region that is allocated on the stack.
*
* Requires:
*

View File

@@ -15,7 +15,7 @@
* WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/* $Id: socket.c,v 1.193 2001/02/24 23:51:09 gson Exp $ */
/* $Id: socket.c,v 1.194 2001/03/06 01:23:03 bwelling Exp $ */
#include <config.h>
@@ -151,6 +151,11 @@ typedef isc_event_t intev_t;
#endif /* USE_CMSG */
/*
* The number of times a send operation is repeated if the result is EINTR.
*/
#define NRETRIES 10
struct isc_socket {
/* Not locked. */
unsigned int magic;
@@ -1002,15 +1007,20 @@ doio_send(isc_socket_t *sock, isc_socketevent_t *dev) {
#else
char *cmsg = NULL;
#endif
int attempts = 0;
build_msghdr_send(sock, dev, &msghdr, cmsg, iov, &write_count);
resend:
cc = sendmsg(sock->fd, &msghdr, 0);
/*
* Check for error or block condition.
*/
if (cc < 0) {
if (errno == EINTR && ++attempts < NRETRIES)
goto resend;
if (SOFT_ERROR(errno))
return (DOIO_SOFT);
@@ -2476,33 +2486,36 @@ socket_send(isc_socket_t *sock, isc_socketevent_t *dev, isc_task_t *task,
case DOIO_SOFT:
/*
* We couldn't send all or part of the request right now, so
* queue it.
* queue it unless ISC_SOCKFLAG_NORETRY is set.
*/
isc_task_attach(task, &ntask);
dev->attributes |= ISC_SOCKEVENTATTR_ATTACHED;
if ((flags & ISC_SOCKFLAG_NORETRY) == 0) {
isc_task_attach(task, &ntask);
dev->attributes |= ISC_SOCKEVENTATTR_ATTACHED;
if (!have_lock) {
LOCK(&sock->lock);
have_lock = ISC_TRUE;
if (!have_lock) {
LOCK(&sock->lock);
have_lock = ISC_TRUE;
}
/*
* Enqueue the request. If the socket was previously
* not being watched, poke the watcher to start
* paying attention to it.
*/
if (ISC_LIST_EMPTY(sock->send_list))
select_poke(sock->manager, sock->fd,
SELECT_POKE_WRITE);
ISC_LIST_ENQUEUE(sock->send_list, dev, ev_link);
socket_log(sock, NULL, EVENT, NULL, 0, 0,
"socket_send: event %p -> task %p",
dev, ntask);
if ((flags & ISC_SOCKFLAG_IMMEDIATE) != 0)
result = ISC_R_INPROGRESS;
break;
}
/*
* Enqueue the request. If the socket was previously not being
* watched, poke the watcher to start paying attention to it.
*/
if (ISC_LIST_EMPTY(sock->send_list))
select_poke(sock->manager, sock->fd,
SELECT_POKE_WRITE);
ISC_LIST_ENQUEUE(sock->send_list, dev, ev_link);
socket_log(sock, NULL, EVENT, NULL, 0, 0,
"socket_send: event %p -> task %p",
dev, ntask);
if ((flags & ISC_SOCKFLAG_IMMEDIATE) != 0)
result = ISC_R_INPROGRESS;
break;
case DOIO_HARD:
case DOIO_SUCCESS:
if ((flags & ISC_SOCKFLAG_IMMEDIATE) == 0)
@@ -2609,6 +2622,9 @@ isc_socket_sendto2(isc_socket_t *sock, isc_region_t *region,
isc_sockaddr_t *address, struct in6_pktinfo *pktinfo,
isc_socketevent_t *event, unsigned int flags)
{
REQUIRE((flags & ~(ISC_SOCKFLAG_IMMEDIATE|ISC_SOCKFLAG_NORETRY)) == 0);
if ((flags & ISC_SOCKFLAG_NORETRY) != 0)
REQUIRE(sock->type == isc_sockettype_udp);
event->ev_sender = sock;
event->result = ISC_R_UNEXPECTED;
ISC_LIST_INIT(event->bufferlist);