notes.c: use designated initializers for clarity
[git/debian.git] / compat / simple-ipc / ipc-win32.c
blob997f6144344d883584b2991f2684ff383a7c9e55
1 #include "cache.h"
2 #include "abspath.h"
3 #include "gettext.h"
4 #include "simple-ipc.h"
5 #include "strbuf.h"
6 #include "pkt-line.h"
7 #include "thread-utils.h"
8 #include "accctrl.h"
9 #include "aclapi.h"
11 #ifndef SUPPORTS_SIMPLE_IPC
13 * This source file should only be compiled when Simple IPC is supported.
14 * See the top-level Makefile.
16 #error SUPPORTS_SIMPLE_IPC not defined
17 #endif
19 static int initialize_pipe_name(const char *path, wchar_t *wpath, size_t alloc)
21 int off = 0;
22 struct strbuf realpath = STRBUF_INIT;
24 if (!strbuf_realpath(&realpath, path, 0))
25 return -1;
27 off = swprintf(wpath, alloc, L"\\\\.\\pipe\\");
28 if (xutftowcs(wpath + off, realpath.buf, alloc - off) < 0)
29 return -1;
31 /* Handle drive prefix */
32 if (wpath[off] && wpath[off + 1] == L':') {
33 wpath[off + 1] = L'_';
34 off += 2;
37 for (; wpath[off]; off++)
38 if (wpath[off] == L'/')
39 wpath[off] = L'\\';
41 strbuf_release(&realpath);
42 return 0;
45 static enum ipc_active_state get_active_state(wchar_t *pipe_path)
47 if (WaitNamedPipeW(pipe_path, NMPWAIT_USE_DEFAULT_WAIT))
48 return IPC_STATE__LISTENING;
50 if (GetLastError() == ERROR_SEM_TIMEOUT)
51 return IPC_STATE__NOT_LISTENING;
53 if (GetLastError() == ERROR_FILE_NOT_FOUND)
54 return IPC_STATE__PATH_NOT_FOUND;
56 trace2_data_intmax("ipc-debug", NULL, "getstate/waitpipe/gle",
57 (intmax_t)GetLastError());
59 return IPC_STATE__OTHER_ERROR;
62 enum ipc_active_state ipc_get_active_state(const char *path)
64 wchar_t pipe_path[MAX_PATH];
66 if (initialize_pipe_name(path, pipe_path, ARRAY_SIZE(pipe_path)) < 0)
67 return IPC_STATE__INVALID_PATH;
69 return get_active_state(pipe_path);
72 #define WAIT_STEP_MS (50)
74 static enum ipc_active_state connect_to_server(
75 const wchar_t *wpath,
76 DWORD timeout_ms,
77 const struct ipc_client_connect_options *options,
78 int *pfd)
80 DWORD t_start_ms, t_waited_ms;
81 DWORD step_ms;
82 HANDLE hPipe = INVALID_HANDLE_VALUE;
83 DWORD mode = PIPE_READMODE_BYTE;
84 DWORD gle;
86 *pfd = -1;
88 for (;;) {
89 hPipe = CreateFileW(wpath, GENERIC_READ | GENERIC_WRITE,
90 0, NULL, OPEN_EXISTING, 0, NULL);
91 if (hPipe != INVALID_HANDLE_VALUE)
92 break;
94 gle = GetLastError();
96 switch (gle) {
97 case ERROR_FILE_NOT_FOUND:
98 if (!options->wait_if_not_found)
99 return IPC_STATE__PATH_NOT_FOUND;
100 if (!timeout_ms)
101 return IPC_STATE__PATH_NOT_FOUND;
103 step_ms = (timeout_ms < WAIT_STEP_MS) ?
104 timeout_ms : WAIT_STEP_MS;
105 sleep_millisec(step_ms);
107 timeout_ms -= step_ms;
108 break; /* try again */
110 case ERROR_PIPE_BUSY:
111 if (!options->wait_if_busy)
112 return IPC_STATE__NOT_LISTENING;
113 if (!timeout_ms)
114 return IPC_STATE__NOT_LISTENING;
116 t_start_ms = (DWORD)(getnanotime() / 1000000);
118 if (!WaitNamedPipeW(wpath, timeout_ms)) {
119 DWORD gleWait = GetLastError();
121 if (gleWait == ERROR_SEM_TIMEOUT)
122 return IPC_STATE__NOT_LISTENING;
124 trace2_data_intmax("ipc-debug", NULL,
125 "connect/waitpipe/gle",
126 (intmax_t)gleWait);
128 return IPC_STATE__OTHER_ERROR;
132 * A pipe server instance became available.
133 * Race other client processes to connect to
134 * it.
136 * But first decrement our overall timeout so
137 * that we don't starve if we keep losing the
138 * race. But also guard against special
139 * NPMWAIT_ values (0 and -1).
141 t_waited_ms = (DWORD)(getnanotime() / 1000000) - t_start_ms;
142 if (t_waited_ms < timeout_ms)
143 timeout_ms -= t_waited_ms;
144 else
145 timeout_ms = 1;
146 break; /* try again */
148 default:
149 trace2_data_intmax("ipc-debug", NULL,
150 "connect/createfile/gle",
151 (intmax_t)gle);
153 return IPC_STATE__OTHER_ERROR;
157 if (!SetNamedPipeHandleState(hPipe, &mode, NULL, NULL)) {
158 gle = GetLastError();
159 trace2_data_intmax("ipc-debug", NULL,
160 "connect/setpipestate/gle",
161 (intmax_t)gle);
163 CloseHandle(hPipe);
164 return IPC_STATE__OTHER_ERROR;
167 *pfd = _open_osfhandle((intptr_t)hPipe, O_RDWR|O_BINARY);
168 if (*pfd < 0) {
169 gle = GetLastError();
170 trace2_data_intmax("ipc-debug", NULL,
171 "connect/openosfhandle/gle",
172 (intmax_t)gle);
174 CloseHandle(hPipe);
175 return IPC_STATE__OTHER_ERROR;
178 /* fd now owns hPipe */
180 return IPC_STATE__LISTENING;
184 * The default connection timeout for Windows clients.
186 * This is not currently part of the ipc_ API (nor the config settings)
187 * because of differences between Windows and other platforms.
189 * This value was chosen at random.
191 #define WINDOWS_CONNECTION_TIMEOUT_MS (30000)
193 enum ipc_active_state ipc_client_try_connect(
194 const char *path,
195 const struct ipc_client_connect_options *options,
196 struct ipc_client_connection **p_connection)
198 wchar_t wpath[MAX_PATH];
199 enum ipc_active_state state = IPC_STATE__OTHER_ERROR;
200 int fd = -1;
202 *p_connection = NULL;
204 trace2_region_enter("ipc-client", "try-connect", NULL);
205 trace2_data_string("ipc-client", NULL, "try-connect/path", path);
207 if (initialize_pipe_name(path, wpath, ARRAY_SIZE(wpath)) < 0)
208 state = IPC_STATE__INVALID_PATH;
209 else
210 state = connect_to_server(wpath, WINDOWS_CONNECTION_TIMEOUT_MS,
211 options, &fd);
213 trace2_data_intmax("ipc-client", NULL, "try-connect/state",
214 (intmax_t)state);
215 trace2_region_leave("ipc-client", "try-connect", NULL);
217 if (state == IPC_STATE__LISTENING) {
218 (*p_connection) = xcalloc(1, sizeof(struct ipc_client_connection));
219 (*p_connection)->fd = fd;
222 return state;
225 void ipc_client_close_connection(struct ipc_client_connection *connection)
227 if (!connection)
228 return;
230 if (connection->fd != -1)
231 close(connection->fd);
233 free(connection);
236 int ipc_client_send_command_to_connection(
237 struct ipc_client_connection *connection,
238 const char *message, size_t message_len,
239 struct strbuf *answer)
241 int ret = 0;
243 strbuf_setlen(answer, 0);
245 trace2_region_enter("ipc-client", "send-command", NULL);
247 if (write_packetized_from_buf_no_flush(message, message_len,
248 connection->fd) < 0 ||
249 packet_flush_gently(connection->fd) < 0) {
250 ret = error(_("could not send IPC command"));
251 goto done;
254 FlushFileBuffers((HANDLE)_get_osfhandle(connection->fd));
256 if (read_packetized_to_strbuf(
257 connection->fd, answer,
258 PACKET_READ_GENTLE_ON_EOF | PACKET_READ_GENTLE_ON_READ_ERROR) < 0) {
259 ret = error(_("could not read IPC response"));
260 goto done;
263 done:
264 trace2_region_leave("ipc-client", "send-command", NULL);
265 return ret;
268 int ipc_client_send_command(const char *path,
269 const struct ipc_client_connect_options *options,
270 const char *message, size_t message_len,
271 struct strbuf *response)
273 int ret = -1;
274 enum ipc_active_state state;
275 struct ipc_client_connection *connection = NULL;
277 state = ipc_client_try_connect(path, options, &connection);
279 if (state != IPC_STATE__LISTENING)
280 return ret;
282 ret = ipc_client_send_command_to_connection(connection,
283 message, message_len,
284 response);
286 ipc_client_close_connection(connection);
288 return ret;
292 * Duplicate the given pipe handle and wrap it in a file descriptor so
293 * that we can use pkt-line on it.
295 static int dup_fd_from_pipe(const HANDLE pipe)
297 HANDLE process = GetCurrentProcess();
298 HANDLE handle;
299 int fd;
301 if (!DuplicateHandle(process, pipe, process, &handle, 0, FALSE,
302 DUPLICATE_SAME_ACCESS)) {
303 errno = err_win_to_posix(GetLastError());
304 return -1;
307 fd = _open_osfhandle((intptr_t)handle, O_RDWR|O_BINARY);
308 if (fd < 0) {
309 errno = err_win_to_posix(GetLastError());
310 CloseHandle(handle);
311 return -1;
315 * `handle` is now owned by `fd` and will be automatically closed
316 * when the descriptor is closed.
319 return fd;
323 * Magic numbers used to annotate callback instance data.
324 * These are used to help guard against accidentally passing the
325 * wrong instance data across multiple levels of callbacks (which
326 * is easy to do if there are `void*` arguments).
328 enum magic {
329 MAGIC_SERVER_REPLY_DATA,
330 MAGIC_SERVER_THREAD_DATA,
331 MAGIC_SERVER_DATA,
334 struct ipc_server_reply_data {
335 enum magic magic;
336 int fd;
337 struct ipc_server_thread_data *server_thread_data;
340 struct ipc_server_thread_data {
341 enum magic magic;
342 struct ipc_server_thread_data *next_thread;
343 struct ipc_server_data *server_data;
344 pthread_t pthread_id;
345 HANDLE hPipe;
349 * On Windows, the conceptual "ipc-server" is implemented as a pool of
350 * n idential/peer "server-thread" threads. That is, there is no
351 * hierarchy of threads; and therefore no controller thread managing
352 * the pool. Each thread has an independent handle to the named pipe,
353 * receives incoming connections, processes the client, and re-uses
354 * the pipe for the next client connection.
356 * Therefore, the "ipc-server" only needs to maintain a list of the
357 * spawned threads for eventual "join" purposes.
359 * A single "stop-event" is visible to all of the server threads to
360 * tell them to shutdown (when idle).
362 struct ipc_server_data {
363 enum magic magic;
364 ipc_server_application_cb *application_cb;
365 void *application_data;
366 struct strbuf buf_path;
367 wchar_t wpath[MAX_PATH];
369 HANDLE hEventStopRequested;
370 struct ipc_server_thread_data *thread_list;
371 int is_stopped;
374 enum connect_result {
375 CR_CONNECTED = 0,
376 CR_CONNECT_PENDING,
377 CR_CONNECT_ERROR,
378 CR_WAIT_ERROR,
379 CR_SHUTDOWN,
382 static enum connect_result queue_overlapped_connect(
383 struct ipc_server_thread_data *server_thread_data,
384 OVERLAPPED *lpo)
386 if (ConnectNamedPipe(server_thread_data->hPipe, lpo))
387 goto failed;
389 switch (GetLastError()) {
390 case ERROR_IO_PENDING:
391 return CR_CONNECT_PENDING;
393 case ERROR_PIPE_CONNECTED:
394 SetEvent(lpo->hEvent);
395 return CR_CONNECTED;
397 default:
398 break;
401 failed:
402 error(_("ConnectNamedPipe failed for '%s' (%lu)"),
403 server_thread_data->server_data->buf_path.buf,
404 GetLastError());
405 return CR_CONNECT_ERROR;
409 * Use Windows Overlapped IO to wait for a connection or for our event
410 * to be signalled.
412 static enum connect_result wait_for_connection(
413 struct ipc_server_thread_data *server_thread_data,
414 OVERLAPPED *lpo)
416 enum connect_result r;
417 HANDLE waitHandles[2];
418 DWORD dwWaitResult;
420 r = queue_overlapped_connect(server_thread_data, lpo);
421 if (r != CR_CONNECT_PENDING)
422 return r;
424 waitHandles[0] = server_thread_data->server_data->hEventStopRequested;
425 waitHandles[1] = lpo->hEvent;
427 dwWaitResult = WaitForMultipleObjects(2, waitHandles, FALSE, INFINITE);
428 switch (dwWaitResult) {
429 case WAIT_OBJECT_0 + 0:
430 return CR_SHUTDOWN;
432 case WAIT_OBJECT_0 + 1:
433 ResetEvent(lpo->hEvent);
434 return CR_CONNECTED;
436 default:
437 return CR_WAIT_ERROR;
442 * Forward declare our reply callback function so that any compiler
443 * errors are reported when we actually define the function (in addition
444 * to any errors reported when we try to pass this callback function as
445 * a parameter in a function call). The former are easier to understand.
447 static ipc_server_reply_cb do_io_reply_callback;
450 * Relay application's response message to the client process.
451 * (We do not flush at this point because we allow the caller
452 * to chunk data to the client thru us.)
454 static int do_io_reply_callback(struct ipc_server_reply_data *reply_data,
455 const char *response, size_t response_len)
457 if (reply_data->magic != MAGIC_SERVER_REPLY_DATA)
458 BUG("reply_cb called with wrong instance data");
460 return write_packetized_from_buf_no_flush(response, response_len,
461 reply_data->fd);
465 * Receive the request/command from the client and pass it to the
466 * registered request-callback. The request-callback will compose
467 * a response and call our reply-callback to send it to the client.
469 * Simple-IPC only contains one round trip, so we flush and close
470 * here after the response.
472 static int do_io(struct ipc_server_thread_data *server_thread_data)
474 struct strbuf buf = STRBUF_INIT;
475 struct ipc_server_reply_data reply_data;
476 int ret = 0;
478 reply_data.magic = MAGIC_SERVER_REPLY_DATA;
479 reply_data.server_thread_data = server_thread_data;
481 reply_data.fd = dup_fd_from_pipe(server_thread_data->hPipe);
482 if (reply_data.fd < 0)
483 return error(_("could not create fd from pipe for '%s'"),
484 server_thread_data->server_data->buf_path.buf);
486 ret = read_packetized_to_strbuf(
487 reply_data.fd, &buf,
488 PACKET_READ_GENTLE_ON_EOF | PACKET_READ_GENTLE_ON_READ_ERROR);
489 if (ret >= 0) {
490 ret = server_thread_data->server_data->application_cb(
491 server_thread_data->server_data->application_data,
492 buf.buf, buf.len, do_io_reply_callback, &reply_data);
494 packet_flush_gently(reply_data.fd);
496 FlushFileBuffers((HANDLE)_get_osfhandle((reply_data.fd)));
498 else {
500 * The client probably disconnected/shutdown before it
501 * could send a well-formed message. Ignore it.
505 strbuf_release(&buf);
506 close(reply_data.fd);
508 return ret;
512 * Handle IPC request and response with this connected client. And reset
513 * the pipe to prepare for the next client.
515 static int use_connection(struct ipc_server_thread_data *server_thread_data)
517 int ret;
519 ret = do_io(server_thread_data);
521 FlushFileBuffers(server_thread_data->hPipe);
522 DisconnectNamedPipe(server_thread_data->hPipe);
524 return ret;
528 * Thread proc for an IPC server worker thread. It handles a series of
529 * connections from clients. It cleans and reuses the hPipe between each
530 * client.
532 static void *server_thread_proc(void *_server_thread_data)
534 struct ipc_server_thread_data *server_thread_data = _server_thread_data;
535 HANDLE hEventConnected = INVALID_HANDLE_VALUE;
536 OVERLAPPED oConnect;
537 enum connect_result cr;
538 int ret;
540 assert(server_thread_data->hPipe != INVALID_HANDLE_VALUE);
542 trace2_thread_start("ipc-server");
543 trace2_data_string("ipc-server", NULL, "pipe",
544 server_thread_data->server_data->buf_path.buf);
546 hEventConnected = CreateEventW(NULL, TRUE, FALSE, NULL);
548 memset(&oConnect, 0, sizeof(oConnect));
549 oConnect.hEvent = hEventConnected;
551 for (;;) {
552 cr = wait_for_connection(server_thread_data, &oConnect);
554 switch (cr) {
555 case CR_SHUTDOWN:
556 goto finished;
558 case CR_CONNECTED:
559 ret = use_connection(server_thread_data);
560 if (ret == SIMPLE_IPC_QUIT) {
561 ipc_server_stop_async(
562 server_thread_data->server_data);
563 goto finished;
565 if (ret > 0) {
567 * Ignore (transient) IO errors with this
568 * client and reset for the next client.
571 break;
573 case CR_CONNECT_PENDING:
574 /* By construction, this should not happen. */
575 BUG("ipc-server[%s]: unexpeced CR_CONNECT_PENDING",
576 server_thread_data->server_data->buf_path.buf);
578 case CR_CONNECT_ERROR:
579 case CR_WAIT_ERROR:
581 * Ignore these theoretical errors.
583 DisconnectNamedPipe(server_thread_data->hPipe);
584 break;
586 default:
587 BUG("unandled case after wait_for_connection");
591 finished:
592 CloseHandle(server_thread_data->hPipe);
593 CloseHandle(hEventConnected);
595 trace2_thread_exit();
596 return NULL;
600 * We need to build a Windows "SECURITY_ATTRIBUTES" object and use it
601 * to apply an ACL when we create the initial instance of the Named
602 * Pipe. The construction is somewhat involved and consists of
603 * several sequential steps and intermediate objects.
605 * We use this structure to hold these intermediate pointers so that
606 * we can free them as a group. (It is unclear from the docs whether
607 * some of these intermediate pointers can be freed before we are
608 * finished using the "lpSA" member.)
610 struct my_sa_data
612 PSID pEveryoneSID;
613 PACL pACL;
614 PSECURITY_DESCRIPTOR pSD;
615 LPSECURITY_ATTRIBUTES lpSA;
618 static void init_sa(struct my_sa_data *d)
620 memset(d, 0, sizeof(*d));
623 static void release_sa(struct my_sa_data *d)
625 if (d->pEveryoneSID)
626 FreeSid(d->pEveryoneSID);
627 if (d->pACL)
628 LocalFree(d->pACL);
629 if (d->pSD)
630 LocalFree(d->pSD);
631 if (d->lpSA)
632 LocalFree(d->lpSA);
634 memset(d, 0, sizeof(*d));
638 * Create SECURITY_ATTRIBUTES to apply to the initial named pipe. The
639 * creator of the first server instance gets to set the ACLs on it.
641 * We allow the well-known group `EVERYONE` to have read+write access
642 * to the named pipe so that clients can send queries to the daemon
643 * and receive the response.
645 * Normally, this is not necessary since the daemon is usually
646 * automatically started by a foreground command like `git status`,
647 * but in those cases where an elevated Git command started the daemon
648 * (such that the daemon itself runs with elevation), we need to add
649 * the ACL so that non-elevated commands can write to it.
651 * The following document was helpful:
652 * https://docs.microsoft.com/en-us/windows/win32/secauthz/creating-a-security-descriptor-for-a-new-object-in-c--
654 * Returns d->lpSA set to a SA or NULL.
656 static LPSECURITY_ATTRIBUTES get_sa(struct my_sa_data *d)
658 SID_IDENTIFIER_AUTHORITY sid_auth_world = SECURITY_WORLD_SID_AUTHORITY;
659 #define NR_EA (1)
660 EXPLICIT_ACCESS ea[NR_EA];
661 DWORD dwResult;
663 if (!AllocateAndInitializeSid(&sid_auth_world, 1,
664 SECURITY_WORLD_RID, 0,0,0,0,0,0,0,
665 &d->pEveryoneSID)) {
666 DWORD gle = GetLastError();
667 trace2_data_intmax("ipc-debug", NULL, "alloc-world-sid/gle",
668 (intmax_t)gle);
669 goto fail;
672 memset(ea, 0, NR_EA * sizeof(EXPLICIT_ACCESS));
674 ea[0].grfAccessPermissions = GENERIC_READ | GENERIC_WRITE;
675 ea[0].grfAccessMode = SET_ACCESS;
676 ea[0].grfInheritance = NO_INHERITANCE;
677 ea[0].Trustee.MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
678 ea[0].Trustee.TrusteeForm = TRUSTEE_IS_SID;
679 ea[0].Trustee.TrusteeType = TRUSTEE_IS_WELL_KNOWN_GROUP;
680 ea[0].Trustee.ptstrName = (LPTSTR)d->pEveryoneSID;
682 dwResult = SetEntriesInAcl(NR_EA, ea, NULL, &d->pACL);
683 if (dwResult != ERROR_SUCCESS) {
684 DWORD gle = GetLastError();
685 trace2_data_intmax("ipc-debug", NULL, "set-acl-entry/gle",
686 (intmax_t)gle);
687 trace2_data_intmax("ipc-debug", NULL, "set-acl-entry/dw",
688 (intmax_t)dwResult);
689 goto fail;
692 d->pSD = (PSECURITY_DESCRIPTOR)LocalAlloc(
693 LPTR, SECURITY_DESCRIPTOR_MIN_LENGTH);
694 if (!InitializeSecurityDescriptor(d->pSD, SECURITY_DESCRIPTOR_REVISION)) {
695 DWORD gle = GetLastError();
696 trace2_data_intmax("ipc-debug", NULL, "init-sd/gle", (intmax_t)gle);
697 goto fail;
700 if (!SetSecurityDescriptorDacl(d->pSD, TRUE, d->pACL, FALSE)) {
701 DWORD gle = GetLastError();
702 trace2_data_intmax("ipc-debug", NULL, "set-sd-dacl/gle", (intmax_t)gle);
703 goto fail;
706 d->lpSA = (LPSECURITY_ATTRIBUTES)LocalAlloc(LPTR, sizeof(SECURITY_ATTRIBUTES));
707 d->lpSA->nLength = sizeof(SECURITY_ATTRIBUTES);
708 d->lpSA->lpSecurityDescriptor = d->pSD;
709 d->lpSA->bInheritHandle = FALSE;
711 return d->lpSA;
713 fail:
714 release_sa(d);
715 return NULL;
718 static HANDLE create_new_pipe(wchar_t *wpath, int is_first)
720 HANDLE hPipe;
721 DWORD dwOpenMode, dwPipeMode;
722 struct my_sa_data my_sa_data;
724 init_sa(&my_sa_data);
726 dwOpenMode = PIPE_ACCESS_INBOUND | PIPE_ACCESS_OUTBOUND |
727 FILE_FLAG_OVERLAPPED;
729 dwPipeMode = PIPE_TYPE_MESSAGE | PIPE_READMODE_BYTE | PIPE_WAIT |
730 PIPE_REJECT_REMOTE_CLIENTS;
732 if (is_first) {
733 dwOpenMode |= FILE_FLAG_FIRST_PIPE_INSTANCE;
736 * On Windows, the first server pipe instance gets to
737 * set the ACL / Security Attributes on the named
738 * pipe; subsequent instances inherit and cannot
739 * change them.
741 get_sa(&my_sa_data);
744 hPipe = CreateNamedPipeW(wpath, dwOpenMode, dwPipeMode,
745 PIPE_UNLIMITED_INSTANCES, 1024, 1024, 0,
746 my_sa_data.lpSA);
748 release_sa(&my_sa_data);
750 return hPipe;
753 int ipc_server_run_async(struct ipc_server_data **returned_server_data,
754 const char *path, const struct ipc_server_opts *opts,
755 ipc_server_application_cb *application_cb,
756 void *application_data)
758 struct ipc_server_data *server_data;
759 wchar_t wpath[MAX_PATH];
760 HANDLE hPipeFirst = INVALID_HANDLE_VALUE;
761 int k;
762 int ret = 0;
763 int nr_threads = opts->nr_threads;
765 *returned_server_data = NULL;
767 ret = initialize_pipe_name(path, wpath, ARRAY_SIZE(wpath));
768 if (ret < 0) {
769 errno = EINVAL;
770 return -1;
773 hPipeFirst = create_new_pipe(wpath, 1);
774 if (hPipeFirst == INVALID_HANDLE_VALUE) {
775 errno = EADDRINUSE;
776 return -2;
779 server_data = xcalloc(1, sizeof(*server_data));
780 server_data->magic = MAGIC_SERVER_DATA;
781 server_data->application_cb = application_cb;
782 server_data->application_data = application_data;
783 server_data->hEventStopRequested = CreateEvent(NULL, TRUE, FALSE, NULL);
784 strbuf_init(&server_data->buf_path, 0);
785 strbuf_addstr(&server_data->buf_path, path);
786 wcscpy(server_data->wpath, wpath);
788 if (nr_threads < 1)
789 nr_threads = 1;
791 for (k = 0; k < nr_threads; k++) {
792 struct ipc_server_thread_data *std;
794 std = xcalloc(1, sizeof(*std));
795 std->magic = MAGIC_SERVER_THREAD_DATA;
796 std->server_data = server_data;
797 std->hPipe = INVALID_HANDLE_VALUE;
799 std->hPipe = (k == 0)
800 ? hPipeFirst
801 : create_new_pipe(server_data->wpath, 0);
803 if (std->hPipe == INVALID_HANDLE_VALUE) {
805 * If we've reached a pipe instance limit for
806 * this path, just use fewer threads.
808 free(std);
809 break;
812 if (pthread_create(&std->pthread_id, NULL,
813 server_thread_proc, std)) {
815 * Likewise, if we're out of threads, just use
816 * fewer threads than requested.
818 * However, we just give up if we can't even get
819 * one thread. This should not happen.
821 if (k == 0)
822 die(_("could not start thread[0] for '%s'"),
823 path);
825 CloseHandle(std->hPipe);
826 free(std);
827 break;
830 std->next_thread = server_data->thread_list;
831 server_data->thread_list = std;
834 *returned_server_data = server_data;
835 return 0;
838 int ipc_server_stop_async(struct ipc_server_data *server_data)
840 if (!server_data)
841 return 0;
844 * Gently tell all of the ipc_server threads to shutdown.
845 * This will be seen the next time they are idle (and waiting
846 * for a connection).
848 * We DO NOT attempt to force them to drop an active connection.
850 SetEvent(server_data->hEventStopRequested);
851 return 0;
854 int ipc_server_await(struct ipc_server_data *server_data)
856 DWORD dwWaitResult;
858 if (!server_data)
859 return 0;
861 dwWaitResult = WaitForSingleObject(server_data->hEventStopRequested, INFINITE);
862 if (dwWaitResult != WAIT_OBJECT_0)
863 return error(_("wait for hEvent failed for '%s'"),
864 server_data->buf_path.buf);
866 while (server_data->thread_list) {
867 struct ipc_server_thread_data *std = server_data->thread_list;
869 pthread_join(std->pthread_id, NULL);
871 server_data->thread_list = std->next_thread;
872 free(std);
875 server_data->is_stopped = 1;
877 return 0;
880 void ipc_server_free(struct ipc_server_data *server_data)
882 if (!server_data)
883 return;
885 if (!server_data->is_stopped)
886 BUG("cannot free ipc-server while running for '%s'",
887 server_data->buf_path.buf);
889 strbuf_release(&server_data->buf_path);
891 if (server_data->hEventStopRequested != INVALID_HANDLE_VALUE)
892 CloseHandle(server_data->hEventStopRequested);
894 while (server_data->thread_list) {
895 struct ipc_server_thread_data *std = server_data->thread_list;
897 server_data->thread_list = std->next_thread;
898 free(std);
901 free(server_data);