bb_info_msg: make it do atomic, unbuffered writes
authorDenis Vlasenko <vda.linux@googlemail.com>
Wed, 10 Dec 2008 11:16:47 +0000 (11:16 -0000)
committerDenis Vlasenko <vda.linux@googlemail.com>
Wed, 10 Dec 2008 11:16:47 +0000 (11:16 -0000)
udhcpc: fix a problem where we don't open listening socket fast enough

function                                             old     new   delta
bb_info_msg                                           70     126     +56
change_listen_mode                                    37      78     +41
udhcp_listen_socket                                  151     124     -27
udhcpc_main                                         2344    2285     -59

libbb/info_msg.c
networking/udhcp/dhcpc.c

index ffef05e54636a9305322743fcd8baa45ddb19398..8b8a1fcca269d7f4311faac89f74bef95ebe9c85 100644 (file)
@@ -12,6 +12,7 @@
 
 void FAST_FUNC bb_info_msg(const char *s, ...)
 {
+#ifdef THIS_ONE_DOESNT_DO_SINGLE_WRITE
        va_list p;
        /* va_copy is used because it is not portable
         * to use va_list p twice */
@@ -27,4 +28,29 @@ void FAST_FUNC bb_info_msg(const char *s, ...)
                vsyslog(LOG_INFO, s, p2);
        va_end(p2);
        va_end(p);
+#else
+       int used;
+       char *msg;
+       va_list p;
+
+       if (logmode == 0)
+               return;
+
+       va_start(p, s);
+       used = vasprintf(&msg, s, p);
+       if (used < 0)
+               return;
+
+       if (ENABLE_FEATURE_SYSLOG && (logmode & LOGMODE_SYSLOG))
+               syslog(LOG_INFO, "%s", msg);
+       if (logmode & LOGMODE_STDIO) {
+               fflush(stdout);
+               /* used = strlen(msg); - must be true already */
+               msg[used++] = '\n';
+               full_write(STDOUT_FILENO, msg, used);
+       }
+
+       free(msg);
+       va_end(p);
+#endif
 }
index e2e5b0a82382f2939e2ad1fbd0a8369004eba2e2..115cddbf0fbfbc9f2f996680cb441f5951011667 100644 (file)
@@ -43,11 +43,17 @@ static void change_listen_mode(int new_mode)
 {
        DEBUG("entering %s listen mode",
                new_mode ? (new_mode == 1 ? "kernel" : "raw") : "none");
+
+       listen_mode = new_mode;
        if (sockfd >= 0) {
                close(sockfd);
                sockfd = -1;
        }
-       listen_mode = new_mode;
+       if (new_mode == LISTEN_KERNEL)
+               sockfd = udhcp_listen_socket(/*INADDR_ANY,*/ CLIENT_PORT, client_config.interface);
+       else if (new_mode != LISTEN_NONE)
+               sockfd = udhcp_raw_socket(client_config.ifindex);
+       /* else LISTEN_NONE: sockfd stay closed */
 }
 
 
@@ -320,12 +326,15 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv)
        for (;;) {
                unsigned timestamp_before_wait;
 
-               if (listen_mode != LISTEN_NONE && sockfd < 0) {
-                       if (listen_mode == LISTEN_KERNEL)
-                               sockfd = udhcp_listen_socket(/*INADDR_ANY,*/ CLIENT_PORT, client_config.interface);
-                       else
-                               sockfd = udhcp_raw_socket(client_config.ifindex);
-               }
+               //bb_error_msg("sockfd:%d, listen_mode:%d", sockfd, listen_mode);
+
+               /* Was opening raw or udp socket here
+                * if (listen_mode != LISTEN_NONE && sockfd < 0),
+                * but on fast network renew responses return faster
+                * than we open sockets. Thus this code is moved
+                * to change_listen_mode(). Thus we open listen socket
+                * BEFORE we send renew request (see "case BOUND:"). */
+
                max_fd = udhcp_sp_fd_set(&rfds, sockfd);
 
                tv.tv_sec = timeout - already_waited_sec;