From: Vincent Bernat Date: Tue, 8 Jul 2014 20:15:12 +0000 (+0200) Subject: snmp: use poll() to wait for AgentX socket to be ready X-Git-Tag: 0.7.10~24 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=ea51049df88240fa47adea1eddfd6905d12f1439;p=thirdparty%2Flldpd.git snmp: use poll() to wait for AgentX socket to be ready Instead of sleeping for an arbitrary amount of time, query if the socket is ready using poll() which should be portable enough (POSIX.1-2001) to work everywhere. --- diff --git a/src/daemon/agent_priv.c b/src/daemon/agent_priv.c index 88e8e958..8efcb5e3 100644 --- a/src/daemon/agent_priv.c +++ b/src/daemon/agent_priv.c @@ -24,6 +24,7 @@ #include #include +#include #ifdef ENABLE_PRIVSEP #include @@ -59,6 +60,7 @@ agent_priv_unix_recv(netsnmp_transport *t, void *buf, int size, goto recv_error; while (rc < 0) { rc = recv(t->sock, buf, size, 0); + /* TODO: handle the (unlikely) case where we get EAGAIN or EWOULDBLOCK */ if (rc < 0 && errno != EINTR) { log_warn("snmp", "unable to receive from fd %d", t->sock); @@ -76,31 +78,46 @@ recv_error: return -1; } +#define AGENT_WRITE_TIMEOUT 2000 static int agent_priv_unix_send(netsnmp_transport *t, void *buf, int size, void **opaque, int *olength) { - int rc = -1, retry = 4; - useconds_t usecs = 250000; + int rc = -1; + struct pollfd sagentx = { + .fd = t->sock, + .events = POLLOUT | POLLERR | POLLHUP + }; if (t != NULL && t->sock >= 0) { while (rc < 0) { - rc = send(t->sock, buf, size, 0); - if (rc < 0) { - if (errno == EAGAIN || errno == EWOULDBLOCK) { - if (--retry <= 0) - break; - - log_info("snmp", "%s: retrying after " - "%d secs...\n", __FUNCTION__, - usecs); - usleep(usecs); - continue; - } else if (errno != EINTR) { - log_info("snmp", "%s: failed with %s\n", - __FUNCTION__, strerror(errno)); + rc = poll(&sagentx, 1, AGENT_WRITE_TIMEOUT); + if (rc == 0) { + log_warnx("snmp", + "timeout while communicating with the master agent"); + rc = -1; + break; + } + if (rc > 0) { + /* We can either write or have an error somewhere */ + rc = send(t->sock, buf, size, 0); + if (rc < 0) { + if (errno == EAGAIN || + errno == EWOULDBLOCK || + errno == EINTR) + /* Let's retry */ + continue; + log_warn("snmp", + "error while sending to master agent"); + break; + } + } else { + if (errno != EINTR) { + log_warn("snmp", + "error while attempting to send to master agent"); break; } + continue; } } }