From: Timo Sirainen Date: Sat, 27 Sep 2008 09:20:26 +0000 (+0300) Subject: Added net_listen_unix_unlink_stale() and use it where needed to avoid code duplication. X-Git-Tag: 1.2.alpha2~29 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=d198989a7cac917ba0bd341a76d94e8a32267074;p=thirdparty%2Fdovecot%2Fcore.git Added net_listen_unix_unlink_stale() and use it where needed to avoid code duplication. --HG-- branch : HEAD --- diff --git a/src/auth/main.c b/src/auth/main.c index 6ac13ebda9..a9b4872b95 100644 --- a/src/auth/main.c +++ b/src/auth/main.c @@ -101,7 +101,7 @@ static int create_unix_listener(const char *env, int backlog) unsigned int mask; uid_t uid; gid_t gid; - int fd, i; + int fd; path = getenv(env); if (path == NULL) @@ -117,23 +117,14 @@ static int create_unix_listener(const char *env, int backlog) } old_umask = umask(mask); - for (i = 0; i < 5; i++) { - fd = net_listen_unix(path, backlog); - if (fd != -1) - break; - - if (errno != EADDRINUSE) - i_fatal("net_listen_unix(%s) failed: %m", path); - - /* see if it really exists */ - if (net_connect_unix(path) != -1 || errno != ECONNREFUSED) + fd = net_listen_unix_unlink_stale(path, backlog); + umask(old_umask); + if (fd == -1) { + if (errno == EADDRINUSE) i_fatal("Socket already exists: %s", path); - - /* delete and try again */ - if (unlink(path) < 0) - i_fatal("unlink(%s) failed: %m", path); + else + i_fatal("net_listen_unix(%s) failed: %m", path); } - umask(old_umask); user = getenv(t_strdup_printf("%s_USER", env)); group = getenv(t_strdup_printf("%s_GROUP", env)); diff --git a/src/dict/dict-server.c b/src/dict/dict-server.c index ca2bd56d5d..2ac889fc85 100644 --- a/src/dict/dict-server.c +++ b/src/dict/dict-server.c @@ -521,27 +521,17 @@ static void dict_server_listener_accept(struct dict_server *server) struct dict_server *dict_server_init(const char *path, int fd) { struct dict_server *server; - int i= 0; server = i_new(struct dict_server, 1); server->path = i_strdup(path); server->fd = fd; - while (server->fd == -1) { - server->fd = net_listen_unix(path, 64); - if (server->fd != -1) - break; - - if (errno != EADDRINUSE || ++i == 2) - i_fatal("net_listen_unix(%s) failed: %m", path); - - /* see if it really exists */ - if (net_connect_unix(path) != -1 || errno != ECONNREFUSED) + server->fd = net_listen_unix_unlink_stale(path, 64); + if (server->fd == -1) { + if (errno == EADDRINUSE) i_fatal("Socket already exists: %s", path); - - /* delete and try again */ - if (unlink(path) < 0) - i_fatal("unlink(%s) failed: %m", path); + else + i_fatal("net_listen_unix(%s) failed: %m", path); } server->io = io_add(server->fd, IO_READ, diff --git a/src/lib/network.c b/src/lib/network.c index 33617e9a49..577ab0114c 100644 --- a/src/lib/network.c +++ b/src/lib/network.c @@ -395,6 +395,33 @@ int net_listen_unix(const char *path, int backlog) return -1; } +int net_listen_unix_unlink_stale(const char *path, int backlog) +{ + unsigned int i = 0; + int fd; + + while ((fd = net_listen_unix(path, backlog)) == -1) { + if (errno != EADDRINUSE || ++i == 2) + return -1; + + /* see if it really exists */ + fd = net_connect_unix(path); + if (fd != -1 || errno != ECONNREFUSED) { + if (fd != -1) (void)close(fd); + errno = EADDRINUSE; + return -1; + } + + /* delete and try again */ + if (unlink(path) < 0 && errno != ENOENT) { + i_error("unlink(%s) failed: %m", path); + errno = EADDRINUSE; + return -1; + } + } + return fd; +} + int net_accept(int fd, struct ip_addr *addr, unsigned int *port) { union sockaddr_union so; diff --git a/src/lib/network.h b/src/lib/network.h index a72a685a50..e4623d9bce 100644 --- a/src/lib/network.h +++ b/src/lib/network.h @@ -67,6 +67,10 @@ void net_get_ip_any6(struct ip_addr *ip); int net_listen(const struct ip_addr *my_ip, unsigned int *port, int backlog); /* Listen for connections on an UNIX socket */ int net_listen_unix(const char *path, int backlog); +/* Like net_listen_unix(), but if socket already exists, try to connect to it. + If it fails with ECONNREFUSED, unlink the socket and try creating it + again. */ +int net_listen_unix_unlink_stale(const char *path, int backlog); /* Accept a connection on a socket. Returns -1 if the connection got closed, -2 for other failures */ int net_accept(int fd, struct ip_addr *addr, unsigned int *port); diff --git a/src/lib/unix-socket-create.c b/src/lib/unix-socket-create.c index 1108ef83a7..2d9e0ade09 100644 --- a/src/lib/unix-socket-create.c +++ b/src/lib/unix-socket-create.c @@ -13,10 +13,8 @@ int unix_socket_create(const char *path, int mode, mode_t old_umask; int fd; - (void)unlink(path); - old_umask = umask(0777 ^ mode); - fd = net_listen_unix(path, backlog); + fd = net_listen_unix_unlink_stale(path, backlog); umask(old_umask); if (fd < 0) { diff --git a/src/master/dict-process.c b/src/master/dict-process.c index 3fec00cd8a..b85050b17f 100644 --- a/src/master/dict-process.c +++ b/src/master/dict-process.c @@ -114,37 +114,17 @@ static void dict_process_listen_input(struct dict_process *process) static int dict_process_listen(struct dict_process *process) { mode_t old_umask; - int fd, i = 0; - - for (;;) { - old_umask = umask(0); - process->fd = net_listen_unix(process->path, 64); - umask(old_umask); - - if (process->fd != -1) - break; - - if (errno != EADDRINUSE || ++i == 2) { - i_error("net_listen_unix(%s) failed: %m", - process->path); - return -1; - } - - /* see if it really exists */ - fd = net_connect_unix(process->path); - if (fd != -1 || errno != ECONNREFUSED) { - if (fd != -1) (void)close(fd); + + old_umask = umask(0); + process->fd = net_listen_unix_unlink_stale(process->path, 64); + umask(old_umask); + if (process->fd == -1) { + if (errno == EADDRINUSE) i_error("Socket already exists: %s", process->path); - return -1; - } - - /* delete and try again */ - if (unlink(process->path) < 0 && errno != ENOENT) { - i_error("unlink(%s) failed: %m", process->path); - return -1; - } + else + i_error("net_listen_unix(%s) failed: %m", process->path); + return -1; } - fd_close_on_exec(process->fd, TRUE); process->io = io_add(process->fd, IO_READ, dict_process_listen_input, process);