krb5 commit: Use millisecond timeouts in sendto_kdc.c

Greg Hudson ghudson at MIT.EDU
Fri Apr 12 13:24:29 EDT 2013


https://github.com/krb5/krb5/commit/1a89d2b5b6606c388d862ed2699a1a664bd5bd31
commit 1a89d2b5b6606c388d862ed2699a1a664bd5bd31
Author: Nathaniel McCallum <npmccallum at redhat.com>
Date:   Tue Apr 9 13:23:39 2013 -0400

    Use millisecond timeouts in sendto_kdc.c
    
    Replace the end_time field of struct select_state with an endtime
    argument to cm_select_or_poll, expressed in milliseconds since the
    epoch.  Add a helper function to get the current time in that format.
    Use a millisecond interval argument to service_fds for consistency.
    
    [ghudson at mit.edu: fix overflow issue in get_curtime_ms; service_fds
    interval argument change; log message]

 src/lib/krb5/os/sendto_kdc.c |  119 ++++++++++++++++++------------------------
 1 files changed, 51 insertions(+), 68 deletions(-)

diff --git a/src/lib/krb5/os/sendto_kdc.c b/src/lib/krb5/os/sendto_kdc.c
index cd1d03e..58e0067 100644
--- a/src/lib/krb5/os/sendto_kdc.c
+++ b/src/lib/krb5/os/sendto_kdc.c
@@ -60,6 +60,8 @@
 #define SSF_WRITE 0x02
 #define SSF_EXCEPTION 0x04
 
+typedef krb5_int64 time_ms;
+
 /* Since fd_set is large on some platforms (8K on AIX 5.2), this probably
  * shouldn't be allocated in automatic storage. */
 struct select_state {
@@ -70,7 +72,6 @@ struct select_state {
     fd_set rfds, wfds, xfds;
 #endif
     int nfds;
-    struct timeval end_time;    /* magic: tv_sec==0 => never time out */
 };
 
 static const char *const state_strings[] = {
@@ -446,6 +447,18 @@ cleanup:
 
 #endif
 
+/* Get current time in milliseconds. */
+static krb5_error_code
+get_curtime_ms(time_ms *time_out)
+{
+    struct timeval tv;
+
+    if (gettimeofday(&tv, 0))
+        return errno;
+    *time_out = (time_ms)tv.tv_sec * 1000 + tv.tv_usec / 1000;
+    return 0;
+}
+
 /*
  * Notes:
  *
@@ -470,7 +483,6 @@ static void
 cm_init_selstate(struct select_state *selstate)
 {
     selstate->nfds = 0;
-    selstate->end_time.tv_sec = selstate->end_time.tv_usec = 0;
 #ifndef USE_POLL
     selstate->max = 0;
     FD_ZERO(&selstate->rfds);
@@ -551,63 +563,33 @@ cm_unset_write(struct select_state *selstate, int fd)
 }
 
 static krb5_error_code
-cm_select_or_poll(const struct select_state *in, struct select_state *out,
-                  int *sret)
+cm_select_or_poll(const struct select_state *in, time_ms endtime,
+                  struct select_state *out, int *sret)
 {
-#ifdef USE_POLL
-    struct timeval now;
-    int e, timeout;
-
-    if (in->end_time.tv_sec == 0)
-        timeout = -1;
-    else {
-        e = gettimeofday(&now, NULL);
-        if (e)
-            return e;
-        timeout = (in->end_time.tv_sec - now.tv_sec) * 1000 +
-            (in->end_time.tv_usec - now.tv_usec) / 1000;
-        if (timeout < 0) {
-            *sret = 0;
-            return 0;
-        }
-    }
+#ifndef USE_POLL
+    struct timeval tv;
+#endif
+    krb5_error_code retval;
+    time_ms curtime, interval;
+
+    retval = get_curtime_ms(&curtime);
+    if (retval != 0)
+        return retval;
+    interval = (curtime < endtime) ? endtime - curtime : 0;
+
     /* We don't need a separate copy of the selstate for poll, but use one for
      * consistency with how we use select. */
     *out = *in;
-    *sret = poll(out->fds, out->nfds, timeout);
-    e = SOCKET_ERRNO;
-    return (*sret < 0) ? e : 0;
-#else
-    struct timeval now, *timo;
-    krb5_error_code e;
 
-    *out = *in;
-    e = gettimeofday(&now, NULL);
-    if (e)
-        return e;
-    if (out->end_time.tv_sec == 0) {
-        timo = 0;
-    } else {
-        timo = &out->end_time;
-        out->end_time.tv_sec -= now.tv_sec;
-        out->end_time.tv_usec -= now.tv_usec;
-        if (out->end_time.tv_usec < 0) {
-            out->end_time.tv_usec += 1000000;
-            out->end_time.tv_sec--;
-        }
-        if (out->end_time.tv_sec < 0) {
-            *sret = 0;
-            return 0;
-        }
-    }
-
-    *sret = select(out->max, &out->rfds, &out->wfds, &out->xfds, timo);
-    e = SOCKET_ERRNO;
-
-    if (*sret < 0)
-        return e;
-    return 0;
+#ifdef USE_POLL
+    *sret = poll(out->fds, out->nfds, interval);
+#else
+    tv.tv_sec = interval / 1000;
+    tv.tv_usec = interval % 1000 * 1000;
+    *sret = select(out->max, &out->rfds, &out->wfds, &out->xfds, &tv);
 #endif
+
+    return (*sret < 0) ? SOCKET_ERRNO : 0;
 }
 
 static unsigned int
@@ -1214,26 +1196,26 @@ service_udp_fd(krb5_context context, struct conn_state *conn,
 }
 
 static krb5_boolean
-service_fds(krb5_context context, struct select_state *selstate, int interval,
-            struct conn_state *conns, struct select_state *seltemp,
+service_fds(krb5_context context, struct select_state *selstate,
+            time_ms interval, struct conn_state *conns,
+            struct select_state *seltemp,
             int (*msg_handler)(krb5_context, const krb5_data *, void *),
             void *msg_handler_data, struct conn_state **winner_out)
 {
     int e, selret = 0;
-    struct timeval now;
+    time_ms endtime;
     struct conn_state *state;
 
     *winner_out = NULL;
 
-    e = gettimeofday(&now, NULL);
+    e = get_curtime_ms(&endtime);
     if (e)
         return 1;
-    selstate->end_time = now;
-    selstate->end_time.tv_sec += interval;
+    endtime += interval;
 
     e = 0;
     while (selstate->nfds > 0) {
-        e = cm_select_or_poll(selstate, seltemp, &selret);
+        e = cm_select_or_poll(selstate, endtime, seltemp, &selret);
         if (e == EINTR)
             continue;
         if (e != 0)
@@ -1312,7 +1294,8 @@ k5_sendto(krb5_context context, const krb5_data *message,
           int (*msg_handler)(krb5_context, const krb5_data *, void *),
           void *msg_handler_data)
 {
-    int pass, delay;
+    int pass;
+    time_ms delay;
     krb5_error_code retval;
     struct conn_state *conns = NULL, *state, **tailptr, *next, *winner;
     size_t s;
@@ -1348,7 +1331,7 @@ k5_sendto(krb5_context context, const krb5_data *message,
                 continue;
             if (maybe_send(context, state, sel_state, callback_info))
                 continue;
-            done = service_fds(context, sel_state, 1, conns, seltemp,
+            done = service_fds(context, sel_state, 1000, conns, seltemp,
                                msg_handler, msg_handler_data, &winner);
         }
     }
@@ -1360,23 +1343,23 @@ k5_sendto(krb5_context context, const krb5_data *message,
             continue;
         if (maybe_send(context, state, sel_state, callback_info))
             continue;
-        done = service_fds(context, sel_state, 1, conns, seltemp, msg_handler,
-                           msg_handler_data, &winner);
+        done = service_fds(context, sel_state, 1000, conns, seltemp,
+                           msg_handler, msg_handler_data, &winner);
     }
 
     /* Wait for two seconds at the end of the first pass. */
     if (!done) {
-        done = service_fds(context, sel_state, 2, conns, seltemp, msg_handler,
-                           msg_handler_data, &winner);
+        done = service_fds(context, sel_state, 2000, conns, seltemp,
+                           msg_handler, msg_handler_data, &winner);
     }
 
     /* Make remaining passes over all of the connections. */
-    delay = 4;
+    delay = 4000;
     for (pass = 1; pass < MAX_PASS && !done; pass++) {
         for (state = conns; state != NULL && !done; state = state->next) {
             if (maybe_send(context, state, sel_state, callback_info))
                 continue;
-            done = service_fds(context, sel_state, 1, conns, seltemp,
+            done = service_fds(context, sel_state, 1000, conns, seltemp,
                                msg_handler, msg_handler_data, &winner);
             if (sel_state->nfds == 0)
                 break;


More information about the cvs-krb5 mailing list