simple-ipc: split async server initialization and running
To start an async ipc server, you call ipc_server_run_async(). That initializes the ipc_server_data object, and starts all of the threads running, which may immediately start serving clients. This can create some awkward timing problems, though. In the fsmonitor daemon (the sole user of the simple-ipc system), we want to create the ipc server early in the process, which means we may start serving clients before the rest of the daemon is fully initialized. To solve this, let's break run_async() into two parts: an initialization which allocates all data and spawns the threads (without letting them run), and a start function which actually lets them begin work. Since we have two simple-ipc implementations, we have to handle this twice: - in ipc-unix-socket.c, we have a central listener thread which hands connections off to worker threads using a work_available mutex. We can hold that mutex after init, and release it when we're ready to start. We do need an extra "started" flag so that we know whether the main thread is holding the mutex or not (e.g., if we prematurely stop the server, we want to make sure all of the worker threads are released to hear about the shutdown). - in ipc-win32.c, we don't have a central mutex. So we'll introduce a new startup_barrier mutex, which we'll similarly hold until we're ready to let the threads proceed. We again need a "started" flag here to make sure that we release the barrier mutex when shutting down, so that the sub-threads can proceed to the finish. I've renamed the run_async() function to init_async() to make sure we catch all callers, since they'll now need to call the matching start_async(). We could leave run_async() as a wrapper that does both, but there's not much point. There are only two callers, one of which is fsmonitor, which will want to actually do work between the two calls. And the other is just a test-tool wrapper. For now I've added the start_async() calls in fsmonitor where they would otherwise have happened, so there should be no behavior change with this patch. Signed-off-by: Jeff King <peff@peff.net> Acked-by: Koji Nakamaru <koji.nakamaru@gree.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:

committed by
Junio C Hamano

parent
4f71522dfb
commit
766fce69e9
@ -328,6 +328,7 @@ struct ipc_server_data {
|
||||
int back_pos;
|
||||
int front_pos;
|
||||
|
||||
int started;
|
||||
int shutdown_requested;
|
||||
int is_stopped;
|
||||
};
|
||||
@ -824,10 +825,10 @@ static int setup_listener_socket(
|
||||
/*
|
||||
* Start IPC server in a pool of background threads.
|
||||
*/
|
||||
int ipc_server_run_async(struct ipc_server_data **returned_server_data,
|
||||
const char *path, const struct ipc_server_opts *opts,
|
||||
ipc_server_application_cb *application_cb,
|
||||
void *application_data)
|
||||
int ipc_server_init_async(struct ipc_server_data **returned_server_data,
|
||||
const char *path, const struct ipc_server_opts *opts,
|
||||
ipc_server_application_cb *application_cb,
|
||||
void *application_data)
|
||||
{
|
||||
struct unix_ss_socket *server_socket = NULL;
|
||||
struct ipc_server_data *server_data;
|
||||
@ -888,6 +889,12 @@ int ipc_server_run_async(struct ipc_server_data **returned_server_data,
|
||||
server_data->accept_thread->fd_send_shutdown = sv[0];
|
||||
server_data->accept_thread->fd_wait_shutdown = sv[1];
|
||||
|
||||
/*
|
||||
* Hold work-available mutex so that no work can start until
|
||||
* we unlock it.
|
||||
*/
|
||||
pthread_mutex_lock(&server_data->work_available_mutex);
|
||||
|
||||
if (pthread_create(&server_data->accept_thread->pthread_id, NULL,
|
||||
accept_thread_proc, server_data->accept_thread))
|
||||
die_errno(_("could not start accept_thread '%s'"), path);
|
||||
@ -918,6 +925,15 @@ int ipc_server_run_async(struct ipc_server_data **returned_server_data,
|
||||
return 0;
|
||||
}
|
||||
|
||||
void ipc_server_start_async(struct ipc_server_data *server_data)
|
||||
{
|
||||
if (!server_data || server_data->started)
|
||||
return;
|
||||
|
||||
server_data->started = 1;
|
||||
pthread_mutex_unlock(&server_data->work_available_mutex);
|
||||
}
|
||||
|
||||
/*
|
||||
* Gently tell the IPC server treads to shutdown.
|
||||
* Can be run on any thread.
|
||||
@ -933,7 +949,9 @@ int ipc_server_stop_async(struct ipc_server_data *server_data)
|
||||
|
||||
trace2_region_enter("ipc-server", "server-stop-async", NULL);
|
||||
|
||||
pthread_mutex_lock(&server_data->work_available_mutex);
|
||||
/* If we haven't started yet, we are already holding lock. */
|
||||
if (server_data->started)
|
||||
pthread_mutex_lock(&server_data->work_available_mutex);
|
||||
|
||||
server_data->shutdown_requested = 1;
|
||||
|
||||
|
Reference in New Issue
Block a user