server: use a non-blocking socket when trying to connect

When checking of a 'foot --server' instance is already running, we try
to connect to the UNIX socket we're planning on listening on.

In most cases, this will fail hard and fast. But under certain
circumstances, we can get stuck in connect() waiting for a connection
timeout.

Since it should be possible to establish a connection immediately *if*
there's someone actually listening on the socket, rely on the fact
that connect() will fail with a EINPROGRESS if a connection can *not*
be established immediately (and thus no one is listening on it).
This commit is contained in:
Daniel Eklöf 2019-11-02 23:25:14 +01:00
parent 32129083bd
commit ad26914631
No known key found for this signature in database
GPG key ID: 5BBD4992C116573F

View file

@ -1,6 +1,7 @@
#include "server.h"
#include <unistd.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/socket.h>
@ -231,11 +232,29 @@ try_connect(const char *sock_path)
goto err;
}
/* Use non-blocking, so that we don't get stuck in connect()
* waiting for a timeout */
int flags;
if ((flags = fcntl(fd, F_GETFL)) < 0 ||
fcntl(fd, F_SETFL, flags | O_NONBLOCK))
{
LOG_ERRNO("failed to set O_NONBLOCK");
goto err;
}
struct sockaddr_un addr = {.sun_family = AF_UNIX};
strncpy(addr.sun_path, sock_path, sizeof(addr.sun_path) - 1);
ret = connect(fd, (const struct sockaddr *)&addr, sizeof(addr)) < 0
? CONNECT_FAIL : CONNECT_SUCCESS;
switch (connect(fd, (struct sockaddr *)&addr, sizeof(addr))) {
case 0:
ret = CONNECT_SUCCESS;
break;
case -1:
LOG_DBG("connect() failed: %s", strerror(errno));
ret = CONNECT_FAIL;
break;
}
err:
if (fd != -1)
@ -289,13 +308,13 @@ server_init(const struct config *conf, struct fdm *fdm, struct wayland *wayl)
LOG_ERRNO("%s: failed to listen", addr.sun_path);
goto err;
}
server = malloc(sizeof(*server));
*server = (struct server) {
.conf = conf,
.fdm = fdm,
.wayl = wayl,
.fd = fd,
.sock_path = sock_path,