diff --git a/src/frontend/sock.c b/src/frontend/sock.c
index 27aa1c5653086a8c073b5c8dbb71c441b268e0be..3b9799496df8bf1e70d501393e36b91de0ebd86e 100644 (file)
--- a/src/frontend/sock.c
+++ b/src/frontend/sock.c
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
+#if HAVE_CONFIG_H
+# include "config.h"
+#endif /* HAVE_CONFIG_H */
+
#include "sysdb.h"
#include "core/object.h"
#include "frontend/connection-private.h"
const char *prefix;
int (*opener)(listener_t *);
+ void (*closer)(listener_t *);
} fe_listener_impl_t;
struct sdb_fe_socket {
return 0;
} /* open_unix_sock */
+static void
+close_unix_sock(listener_t *listener)
+{
+ assert(listener);
+ if (! listener->address)
+ return;
+
+ if (listener->sock_fd >= 0)
+ close(listener->sock_fd);
+ listener->sock_fd = -1;
+
+ unlink(listener->address + strlen("unix:"));
+} /* close_unix_sock */
+
/*
* private variables
*/
LISTENER_UNIXSOCK = 0,
};
static fe_listener_impl_t listener_impls[] = {
- { LISTENER_UNIXSOCK, "unix", open_unix_sock },
+ { LISTENER_UNIXSOCK, "unix", open_unix_sock, close_unix_sock },
};
/*
* private helper functions
*/
+static int
+listener_listen(listener_t *listener)
+{
+ assert(listener);
+
+ /* try to reopen */
+ if (listener->sock_fd < 0)
+ if (listener_impls[listener->type].opener(listener))
+ return -1;
+ assert(listener->sock_fd >= 0);
+
+ if (listen(listener->sock_fd, /* backlog = */ 32)) {
+ char buf[1024];
+ sdb_log(SDB_LOG_ERR, "frontend: Failed to listen on socket %s: %s",
+ listener->address, sdb_strerror(errno, buf, sizeof(buf)));
+ return -1;
+ }
+ return 0;
+} /* listener_listen */
+
+static void
+listener_close(listener_t *listener)
+{
+ assert(listener);
+
+ if (listener_impls[listener->type].closer)
+ listener_impls[listener->type].closer(listener);
+
+ if (listener->sock_fd >= 0)
+ close(listener->sock_fd);
+ listener->sock_fd = -1;
+} /* listener_close */
+
static int
get_type(const char *address)
{
if (! listener)
return;
- if (listener->sock_fd >= 0)
- close(listener->sock_fd);
- listener->sock_fd = -1;
+ listener_close(listener);
if (listener->address)
free(listener->address);
+ listener->address = NULL;
} /* listener_destroy */
static listener_t *
}
listener = realloc(sock->listeners,
- sock->listeners_num * sizeof(*sock->listeners));
+ (sock->listeners_num + 1) * sizeof(*sock->listeners));
if (! listener) {
char buf[1024];
sdb_log(SDB_LOG_ERR, "frontend: Failed to allocate memory: %s",
return listener;
} /* listener_create */
-static int
-listener_listen(listener_t *listener)
-{
- assert(listener);
-
- /* try to reopen */
- if (listener->sock_fd < 0)
- if (listener_impls[listener->type].opener(listener))
- return -1;
- assert(listener->sock_fd >= 0);
-
- if (listen(listener->sock_fd, /* backlog = */ 32)) {
- char buf[1024];
- sdb_log(SDB_LOG_ERR, "frontend: Failed to listen on socket %s: %s",
- listener->address, sdb_strerror(errno, buf, sizeof(buf)));
- return -1;
- }
- return 0;
-} /* listener_listen */
-
-static void
-listener_close(listener_t *listener)
-{
- assert(listener);
-
- if (listener->sock_fd < 0)
- return;
-
- close(listener->sock_fd);
- listener->sock_fd = -1;
-} /* listener_close */
-
static void
socket_close(sdb_fe_socket_t *sock)
{
int max_listen_fd = 0;
size_t i;
- /* XXX: make the number of threads configurable */
- pthread_t handler_threads[5];
+ pthread_t handler_threads[loop->num_threads];
+ size_t num_threads;
- if ((! sock) || (! sock->listeners_num) || (! loop) || sock->chan)
+ if ((! sock) || (! sock->listeners_num) || sock->chan
+ || (! loop) || (loop->num_threads <= 0))
return -1;
if (! loop->do_loop)
return -1;
}
+ sdb_log(SDB_LOG_INFO, "frontend: Starting %d connection "
+ "handler thread%s managing %d listener%s",
+ loop->num_threads, loop->num_threads == 1 ? "" : "s",
+ sock->listeners_num, sock->listeners_num == 1 ? "" : "s");
+
+ num_threads = loop->num_threads;
memset(&handler_threads, 0, sizeof(handler_threads));
- /* XXX: error handling */
- for (i = 0; i < SDB_STATIC_ARRAY_LEN(handler_threads); ++i)
- pthread_create(&handler_threads[i], /* attr = */ NULL,
- connection_handler, /* arg = */ sock);
+ for (i = 0; i < num_threads; ++i) {
+ errno = 0;
+ if (pthread_create(&handler_threads[i], /* attr = */ NULL,
+ connection_handler, /* arg = */ sock)) {
+ char errbuf[1024];
+ sdb_log(SDB_LOG_ERR, "frontend: Failed to create "
+ "connection handler thread: %s",
+ sdb_strerror(errno, errbuf, sizeof(errbuf)));
+ num_threads = i;
+ break;
+ }
+ }
- while (loop->do_loop) {
+ while (loop->do_loop && num_threads) {
struct timeval timeout = { 1, 0 }; /* one second */
sdb_llist_iter_t *iter;
sdb_log(SDB_LOG_INFO, "frontend: Waiting for connection handler threads "
"to terminate");
if (! sdb_channel_shutdown(sock->chan))
- for (i = 0; i < SDB_STATIC_ARRAY_LEN(handler_threads); ++i)
+ for (i = 0; i < num_threads; ++i)
pthread_join(handler_threads[i], NULL);
/* else: we tried our best; let the operating system clean up */
sdb_channel_destroy(sock->chan);
sock->chan = NULL;
+
+ if (! num_threads)
+ return -1;
return 0;
} /* sdb_fe_sock_listen_and_server */