]> git.ipfire.org Git - thirdparty/hostap.git/commitdiff
Remove orphaned wpa_cli control socket on EADDRINUSE
authorJouni Malinen <j@w1.fi>
Sat, 31 Jan 2009 20:22:09 +0000 (22:22 +0200)
committerJouni Malinen <j@w1.fi>
Sat, 31 Jan 2009 20:22:09 +0000 (22:22 +0200)
If the bind() on /tmp/wpa_ctrl_<pid>_<in-proc-counter> fails with
EADDRINUSE, there is an existing socket file with the name we are trying
to create. Since getpid() is unique, there cannot be another process
using that socket and we can just unlink the file and try again. This
can speed up client connection if wpa_cli is killed without allowing it
to clean up the socket file. [Bug 288]

src/common/wpa_ctrl.c

index e411602d748195e9642aeb468460d2ab7653a603..2b4e3aa5ee1f72d2ff802f829f06c6ed182f4b60 100644 (file)
@@ -64,6 +64,7 @@ struct wpa_ctrl * wpa_ctrl_open(const char *ctrl_path)
        static int counter = 0;
        int ret;
        size_t res;
+       int tries = 0;
 
        ctrl = os_malloc(sizeof(*ctrl));
        if (ctrl == NULL)
@@ -77,15 +78,28 @@ struct wpa_ctrl * wpa_ctrl_open(const char *ctrl_path)
        }
 
        ctrl->local.sun_family = AF_UNIX;
+       counter++;
+try_again:
        ret = os_snprintf(ctrl->local.sun_path, sizeof(ctrl->local.sun_path),
-                         "/tmp/wpa_ctrl_%d-%d", getpid(), counter++);
+                         "/tmp/wpa_ctrl_%d-%d", getpid(), counter);
        if (ret < 0 || (size_t) ret >= sizeof(ctrl->local.sun_path)) {
                close(ctrl->s);
                os_free(ctrl);
                return NULL;
        }
+       tries++;
        if (bind(ctrl->s, (struct sockaddr *) &ctrl->local,
                    sizeof(ctrl->local)) < 0) {
+               if (errno == EADDRINUSE && tries < 2) {
+                       /*
+                        * getpid() returns unique identifier for this instance
+                        * of wpa_ctrl, so the existing socket file must have
+                        * been left by unclean termination of an earlier run.
+                        * Remove the file and try again.
+                        */
+                       unlink(ctrl->local.sun_path);
+                       goto try_again;
+               }
                close(ctrl->s);
                os_free(ctrl);
                return NULL;