treewide: be explicit about dependence on gettext.h
[git/debian.git] / compat / simple-ipc / ipc-win32.c
blobf011e5cead8ca6aeef2ef0eca5bd53f32e205eaa
1 #include "cache.h"
2 #include "gettext.h"
3 #include "simple-ipc.h"
4 #include "strbuf.h"
5 #include "pkt-line.h"
6 #include "thread-utils.h"
7 #include "accctrl.h"
8 #include "aclapi.h"
10 #ifndef SUPPORTS_SIMPLE_IPC
12 * This source file should only be compiled when Simple IPC is supported.
13 * See the top-level Makefile.
15 #error SUPPORTS_SIMPLE_IPC not defined
16 #endif
18 static int initialize_pipe_name(const char *path, wchar_t *wpath, size_t alloc)
20 int off = 0;
21 struct strbuf realpath = STRBUF_INIT;
23 if (!strbuf_realpath(&realpath, path, 0))
24 return -1;
26 off = swprintf(wpath, alloc, L"\\\\.\\pipe\\");
27 if (xutftowcs(wpath + off, realpath.buf, alloc - off) < 0)
28 return -1;
30 /* Handle drive prefix */
31 if (wpath[off] && wpath[off + 1] == L':') {
32 wpath[off + 1] = L'_';
33 off += 2;
36 for (; wpath[off]; off++)
37 if (wpath[off] == L'/')
38 wpath[off] = L'\\';
40 strbuf_release(&realpath);
41 return 0;
44 static enum ipc_active_state get_active_state(wchar_t *pipe_path)
46 if (WaitNamedPipeW(pipe_path, NMPWAIT_USE_DEFAULT_WAIT))
47 return IPC_STATE__LISTENING;
49 if (GetLastError() == ERROR_SEM_TIMEOUT)
50 return IPC_STATE__NOT_LISTENING;
52 if (GetLastError() == ERROR_FILE_NOT_FOUND)
53 return IPC_STATE__PATH_NOT_FOUND;
55 trace2_data_intmax("ipc-debug", NULL, "getstate/waitpipe/gle",
56 (intmax_t)GetLastError());
58 return IPC_STATE__OTHER_ERROR;
61 enum ipc_active_state ipc_get_active_state(const char *path)
63 wchar_t pipe_path[MAX_PATH];
65 if (initialize_pipe_name(path, pipe_path, ARRAY_SIZE(pipe_path)) < 0)
66 return IPC_STATE__INVALID_PATH;
68 return get_active_state(pipe_path);
71 #define WAIT_STEP_MS (50)
73 static enum ipc_active_state connect_to_server(
74 const wchar_t *wpath,
75 DWORD timeout_ms,
76 const struct ipc_client_connect_options *options,
77 int *pfd)
79 DWORD t_start_ms, t_waited_ms;
80 DWORD step_ms;
81 HANDLE hPipe = INVALID_HANDLE_VALUE;
82 DWORD mode = PIPE_READMODE_BYTE;
83 DWORD gle;
85 *pfd = -1;
87 for (;;) {
88 hPipe = CreateFileW(wpath, GENERIC_READ | GENERIC_WRITE,
89 0, NULL, OPEN_EXISTING, 0, NULL);
90 if (hPipe != INVALID_HANDLE_VALUE)
91 break;
93 gle = GetLastError();
95 switch (gle) {
96 case ERROR_FILE_NOT_FOUND:
97 if (!options->wait_if_not_found)
98 return IPC_STATE__PATH_NOT_FOUND;
99 if (!timeout_ms)
100 return IPC_STATE__PATH_NOT_FOUND;
102 step_ms = (timeout_ms < WAIT_STEP_MS) ?
103 timeout_ms : WAIT_STEP_MS;
104 sleep_millisec(step_ms);
106 timeout_ms -= step_ms;
107 break; /* try again */
109 case ERROR_PIPE_BUSY:
110 if (!options->wait_if_busy)
111 return IPC_STATE__NOT_LISTENING;
112 if (!timeout_ms)
113 return IPC_STATE__NOT_LISTENING;
115 t_start_ms = (DWORD)(getnanotime() / 1000000);
117 if (!WaitNamedPipeW(wpath, timeout_ms)) {
118 DWORD gleWait = GetLastError();
120 if (gleWait == ERROR_SEM_TIMEOUT)
121 return IPC_STATE__NOT_LISTENING;
123 trace2_data_intmax("ipc-debug", NULL,
124 "connect/waitpipe/gle",
125 (intmax_t)gleWait);
127 return IPC_STATE__OTHER_ERROR;
131 * A pipe server instance became available.
132 * Race other client processes to connect to
133 * it.
135 * But first decrement our overall timeout so
136 * that we don't starve if we keep losing the
137 * race. But also guard against special
138 * NPMWAIT_ values (0 and -1).
140 t_waited_ms = (DWORD)(getnanotime() / 1000000) - t_start_ms;
141 if (t_waited_ms < timeout_ms)
142 timeout_ms -= t_waited_ms;
143 else
144 timeout_ms = 1;
145 break; /* try again */
147 default:
148 trace2_data_intmax("ipc-debug", NULL,
149 "connect/createfile/gle",
150 (intmax_t)gle);
152 return IPC_STATE__OTHER_ERROR;
156 if (!SetNamedPipeHandleState(hPipe, &mode, NULL, NULL)) {
157 gle = GetLastError();
158 trace2_data_intmax("ipc-debug", NULL,
159 "connect/setpipestate/gle",
160 (intmax_t)gle);
162 CloseHandle(hPipe);
163 return IPC_STATE__OTHER_ERROR;
166 *pfd = _open_osfhandle((intptr_t)hPipe, O_RDWR|O_BINARY);
167 if (*pfd < 0) {
168 gle = GetLastError();
169 trace2_data_intmax("ipc-debug", NULL,
170 "connect/openosfhandle/gle",
171 (intmax_t)gle);
173 CloseHandle(hPipe);
174 return IPC_STATE__OTHER_ERROR;
177 /* fd now owns hPipe */
179 return IPC_STATE__LISTENING;
183 * The default connection timeout for Windows clients.
185 * This is not currently part of the ipc_ API (nor the config settings)
186 * because of differences between Windows and other platforms.
188 * This value was chosen at random.
190 #define WINDOWS_CONNECTION_TIMEOUT_MS (30000)
192 enum ipc_active_state ipc_client_try_connect(
193 const char *path,
194 const struct ipc_client_connect_options *options,
195 struct ipc_client_connection **p_connection)
197 wchar_t wpath[MAX_PATH];
198 enum ipc_active_state state = IPC_STATE__OTHER_ERROR;
199 int fd = -1;
201 *p_connection = NULL;
203 trace2_region_enter("ipc-client", "try-connect", NULL);
204 trace2_data_string("ipc-client", NULL, "try-connect/path", path);
206 if (initialize_pipe_name(path, wpath, ARRAY_SIZE(wpath)) < 0)
207 state = IPC_STATE__INVALID_PATH;
208 else
209 state = connect_to_server(wpath, WINDOWS_CONNECTION_TIMEOUT_MS,
210 options, &fd);
212 trace2_data_intmax("ipc-client", NULL, "try-connect/state",
213 (intmax_t)state);
214 trace2_region_leave("ipc-client", "try-connect", NULL);
216 if (state == IPC_STATE__LISTENING) {
217 (*p_connection) = xcalloc(1, sizeof(struct ipc_client_connection));
218 (*p_connection)->fd = fd;
221 return state;
224 void ipc_client_close_connection(struct ipc_client_connection *connection)
226 if (!connection)
227 return;
229 if (connection->fd != -1)
230 close(connection->fd);
232 free(connection);
235 int ipc_client_send_command_to_connection(
236 struct ipc_client_connection *connection,
237 const char *message, size_t message_len,
238 struct strbuf *answer)
240 int ret = 0;
242 strbuf_setlen(answer, 0);
244 trace2_region_enter("ipc-client", "send-command", NULL);
246 if (write_packetized_from_buf_no_flush(message, message_len,
247 connection->fd) < 0 ||
248 packet_flush_gently(connection->fd) < 0) {
249 ret = error(_("could not send IPC command"));
250 goto done;
253 FlushFileBuffers((HANDLE)_get_osfhandle(connection->fd));
255 if (read_packetized_to_strbuf(
256 connection->fd, answer,
257 PACKET_READ_GENTLE_ON_EOF | PACKET_READ_GENTLE_ON_READ_ERROR) < 0) {
258 ret = error(_("could not read IPC response"));
259 goto done;
262 done:
263 trace2_region_leave("ipc-client", "send-command", NULL);
264 return ret;
267 int ipc_client_send_command(const char *path,
268 const struct ipc_client_connect_options *options,
269 const char *message, size_t message_len,
270 struct strbuf *response)
272 int ret = -1;
273 enum ipc_active_state state;
274 struct ipc_client_connection *connection = NULL;
276 state = ipc_client_try_connect(path, options, &connection);
278 if (state != IPC_STATE__LISTENING)
279 return ret;
281 ret = ipc_client_send_command_to_connection(connection,
282 message, message_len,
283 response);
285 ipc_client_close_connection(connection);
287 return ret;
291 * Duplicate the given pipe handle and wrap it in a file descriptor so
292 * that we can use pkt-line on it.
294 static int dup_fd_from_pipe(const HANDLE pipe)
296 HANDLE process = GetCurrentProcess();
297 HANDLE handle;
298 int fd;
300 if (!DuplicateHandle(process, pipe, process, &handle, 0, FALSE,
301 DUPLICATE_SAME_ACCESS)) {
302 errno = err_win_to_posix(GetLastError());
303 return -1;
306 fd = _open_osfhandle((intptr_t)handle, O_RDWR|O_BINARY);
307 if (fd < 0) {
308 errno = err_win_to_posix(GetLastError());
309 CloseHandle(handle);
310 return -1;
314 * `handle` is now owned by `fd` and will be automatically closed
315 * when the descriptor is closed.
318 return fd;
322 * Magic numbers used to annotate callback instance data.
323 * These are used to help guard against accidentally passing the
324 * wrong instance data across multiple levels of callbacks (which
325 * is easy to do if there are `void*` arguments).
327 enum magic {
328 MAGIC_SERVER_REPLY_DATA,
329 MAGIC_SERVER_THREAD_DATA,
330 MAGIC_SERVER_DATA,
333 struct ipc_server_reply_data {
334 enum magic magic;
335 int fd;
336 struct ipc_server_thread_data *server_thread_data;
339 struct ipc_server_thread_data {
340 enum magic magic;
341 struct ipc_server_thread_data *next_thread;
342 struct ipc_server_data *server_data;
343 pthread_t pthread_id;
344 HANDLE hPipe;
348 * On Windows, the conceptual "ipc-server" is implemented as a pool of
349 * n idential/peer "server-thread" threads. That is, there is no
350 * hierarchy of threads; and therefore no controller thread managing
351 * the pool. Each thread has an independent handle to the named pipe,
352 * receives incoming connections, processes the client, and re-uses
353 * the pipe for the next client connection.
355 * Therefore, the "ipc-server" only needs to maintain a list of the
356 * spawned threads for eventual "join" purposes.
358 * A single "stop-event" is visible to all of the server threads to
359 * tell them to shutdown (when idle).
361 struct ipc_server_data {
362 enum magic magic;
363 ipc_server_application_cb *application_cb;
364 void *application_data;
365 struct strbuf buf_path;
366 wchar_t wpath[MAX_PATH];
368 HANDLE hEventStopRequested;
369 struct ipc_server_thread_data *thread_list;
370 int is_stopped;
373 enum connect_result {
374 CR_CONNECTED = 0,
375 CR_CONNECT_PENDING,
376 CR_CONNECT_ERROR,
377 CR_WAIT_ERROR,
378 CR_SHUTDOWN,
381 static enum connect_result queue_overlapped_connect(
382 struct ipc_server_thread_data *server_thread_data,
383 OVERLAPPED *lpo)
385 if (ConnectNamedPipe(server_thread_data->hPipe, lpo))
386 goto failed;
388 switch (GetLastError()) {
389 case ERROR_IO_PENDING:
390 return CR_CONNECT_PENDING;
392 case ERROR_PIPE_CONNECTED:
393 SetEvent(lpo->hEvent);
394 return CR_CONNECTED;
396 default:
397 break;
400 failed:
401 error(_("ConnectNamedPipe failed for '%s' (%lu)"),
402 server_thread_data->server_data->buf_path.buf,
403 GetLastError());
404 return CR_CONNECT_ERROR;
408 * Use Windows Overlapped IO to wait for a connection or for our event
409 * to be signalled.
411 static enum connect_result wait_for_connection(
412 struct ipc_server_thread_data *server_thread_data,
413 OVERLAPPED *lpo)
415 enum connect_result r;
416 HANDLE waitHandles[2];
417 DWORD dwWaitResult;
419 r = queue_overlapped_connect(server_thread_data, lpo);
420 if (r != CR_CONNECT_PENDING)
421 return r;
423 waitHandles[0] = server_thread_data->server_data->hEventStopRequested;
424 waitHandles[1] = lpo->hEvent;
426 dwWaitResult = WaitForMultipleObjects(2, waitHandles, FALSE, INFINITE);
427 switch (dwWaitResult) {
428 case WAIT_OBJECT_0 + 0:
429 return CR_SHUTDOWN;
431 case WAIT_OBJECT_0 + 1:
432 ResetEvent(lpo->hEvent);
433 return CR_CONNECTED;
435 default:
436 return CR_WAIT_ERROR;
441 * Forward declare our reply callback function so that any compiler
442 * errors are reported when we actually define the function (in addition
443 * to any errors reported when we try to pass this callback function as
444 * a parameter in a function call). The former are easier to understand.
446 static ipc_server_reply_cb do_io_reply_callback;
449 * Relay application's response message to the client process.
450 * (We do not flush at this point because we allow the caller
451 * to chunk data to the client thru us.)
453 static int do_io_reply_callback(struct ipc_server_reply_data *reply_data,
454 const char *response, size_t response_len)
456 if (reply_data->magic != MAGIC_SERVER_REPLY_DATA)
457 BUG("reply_cb called with wrong instance data");
459 return write_packetized_from_buf_no_flush(response, response_len,
460 reply_data->fd);
464 * Receive the request/command from the client and pass it to the
465 * registered request-callback. The request-callback will compose
466 * a response and call our reply-callback to send it to the client.
468 * Simple-IPC only contains one round trip, so we flush and close
469 * here after the response.
471 static int do_io(struct ipc_server_thread_data *server_thread_data)
473 struct strbuf buf = STRBUF_INIT;
474 struct ipc_server_reply_data reply_data;
475 int ret = 0;
477 reply_data.magic = MAGIC_SERVER_REPLY_DATA;
478 reply_data.server_thread_data = server_thread_data;
480 reply_data.fd = dup_fd_from_pipe(server_thread_data->hPipe);
481 if (reply_data.fd < 0)
482 return error(_("could not create fd from pipe for '%s'"),
483 server_thread_data->server_data->buf_path.buf);
485 ret = read_packetized_to_strbuf(
486 reply_data.fd, &buf,
487 PACKET_READ_GENTLE_ON_EOF | PACKET_READ_GENTLE_ON_READ_ERROR);
488 if (ret >= 0) {
489 ret = server_thread_data->server_data->application_cb(
490 server_thread_data->server_data->application_data,
491 buf.buf, buf.len, do_io_reply_callback, &reply_data);
493 packet_flush_gently(reply_data.fd);
495 FlushFileBuffers((HANDLE)_get_osfhandle((reply_data.fd)));
497 else {
499 * The client probably disconnected/shutdown before it
500 * could send a well-formed message. Ignore it.
504 strbuf_release(&buf);
505 close(reply_data.fd);
507 return ret;
511 * Handle IPC request and response with this connected client. And reset
512 * the pipe to prepare for the next client.
514 static int use_connection(struct ipc_server_thread_data *server_thread_data)
516 int ret;
518 ret = do_io(server_thread_data);
520 FlushFileBuffers(server_thread_data->hPipe);
521 DisconnectNamedPipe(server_thread_data->hPipe);
523 return ret;
527 * Thread proc for an IPC server worker thread. It handles a series of
528 * connections from clients. It cleans and reuses the hPipe between each
529 * client.
531 static void *server_thread_proc(void *_server_thread_data)
533 struct ipc_server_thread_data *server_thread_data = _server_thread_data;
534 HANDLE hEventConnected = INVALID_HANDLE_VALUE;
535 OVERLAPPED oConnect;
536 enum connect_result cr;
537 int ret;
539 assert(server_thread_data->hPipe != INVALID_HANDLE_VALUE);
541 trace2_thread_start("ipc-server");
542 trace2_data_string("ipc-server", NULL, "pipe",
543 server_thread_data->server_data->buf_path.buf);
545 hEventConnected = CreateEventW(NULL, TRUE, FALSE, NULL);
547 memset(&oConnect, 0, sizeof(oConnect));
548 oConnect.hEvent = hEventConnected;
550 for (;;) {
551 cr = wait_for_connection(server_thread_data, &oConnect);
553 switch (cr) {
554 case CR_SHUTDOWN:
555 goto finished;
557 case CR_CONNECTED:
558 ret = use_connection(server_thread_data);
559 if (ret == SIMPLE_IPC_QUIT) {
560 ipc_server_stop_async(
561 server_thread_data->server_data);
562 goto finished;
564 if (ret > 0) {
566 * Ignore (transient) IO errors with this
567 * client and reset for the next client.
570 break;
572 case CR_CONNECT_PENDING:
573 /* By construction, this should not happen. */
574 BUG("ipc-server[%s]: unexpeced CR_CONNECT_PENDING",
575 server_thread_data->server_data->buf_path.buf);
577 case CR_CONNECT_ERROR:
578 case CR_WAIT_ERROR:
580 * Ignore these theoretical errors.
582 DisconnectNamedPipe(server_thread_data->hPipe);
583 break;
585 default:
586 BUG("unandled case after wait_for_connection");
590 finished:
591 CloseHandle(server_thread_data->hPipe);
592 CloseHandle(hEventConnected);
594 trace2_thread_exit();
595 return NULL;
599 * We need to build a Windows "SECURITY_ATTRIBUTES" object and use it
600 * to apply an ACL when we create the initial instance of the Named
601 * Pipe. The construction is somewhat involved and consists of
602 * several sequential steps and intermediate objects.
604 * We use this structure to hold these intermediate pointers so that
605 * we can free them as a group. (It is unclear from the docs whether
606 * some of these intermediate pointers can be freed before we are
607 * finished using the "lpSA" member.)
609 struct my_sa_data
611 PSID pEveryoneSID;
612 PACL pACL;
613 PSECURITY_DESCRIPTOR pSD;
614 LPSECURITY_ATTRIBUTES lpSA;
617 static void init_sa(struct my_sa_data *d)
619 memset(d, 0, sizeof(*d));
622 static void release_sa(struct my_sa_data *d)
624 if (d->pEveryoneSID)
625 FreeSid(d->pEveryoneSID);
626 if (d->pACL)
627 LocalFree(d->pACL);
628 if (d->pSD)
629 LocalFree(d->pSD);
630 if (d->lpSA)
631 LocalFree(d->lpSA);
633 memset(d, 0, sizeof(*d));
637 * Create SECURITY_ATTRIBUTES to apply to the initial named pipe. The
638 * creator of the first server instance gets to set the ACLs on it.
640 * We allow the well-known group `EVERYONE` to have read+write access
641 * to the named pipe so that clients can send queries to the daemon
642 * and receive the response.
644 * Normally, this is not necessary since the daemon is usually
645 * automatically started by a foreground command like `git status`,
646 * but in those cases where an elevated Git command started the daemon
647 * (such that the daemon itself runs with elevation), we need to add
648 * the ACL so that non-elevated commands can write to it.
650 * The following document was helpful:
651 * https://docs.microsoft.com/en-us/windows/win32/secauthz/creating-a-security-descriptor-for-a-new-object-in-c--
653 * Returns d->lpSA set to a SA or NULL.
655 static LPSECURITY_ATTRIBUTES get_sa(struct my_sa_data *d)
657 SID_IDENTIFIER_AUTHORITY sid_auth_world = SECURITY_WORLD_SID_AUTHORITY;
658 #define NR_EA (1)
659 EXPLICIT_ACCESS ea[NR_EA];
660 DWORD dwResult;
662 if (!AllocateAndInitializeSid(&sid_auth_world, 1,
663 SECURITY_WORLD_RID, 0,0,0,0,0,0,0,
664 &d->pEveryoneSID)) {
665 DWORD gle = GetLastError();
666 trace2_data_intmax("ipc-debug", NULL, "alloc-world-sid/gle",
667 (intmax_t)gle);
668 goto fail;
671 memset(ea, 0, NR_EA * sizeof(EXPLICIT_ACCESS));
673 ea[0].grfAccessPermissions = GENERIC_READ | GENERIC_WRITE;
674 ea[0].grfAccessMode = SET_ACCESS;
675 ea[0].grfInheritance = NO_INHERITANCE;
676 ea[0].Trustee.MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
677 ea[0].Trustee.TrusteeForm = TRUSTEE_IS_SID;
678 ea[0].Trustee.TrusteeType = TRUSTEE_IS_WELL_KNOWN_GROUP;
679 ea[0].Trustee.ptstrName = (LPTSTR)d->pEveryoneSID;
681 dwResult = SetEntriesInAcl(NR_EA, ea, NULL, &d->pACL);
682 if (dwResult != ERROR_SUCCESS) {
683 DWORD gle = GetLastError();
684 trace2_data_intmax("ipc-debug", NULL, "set-acl-entry/gle",
685 (intmax_t)gle);
686 trace2_data_intmax("ipc-debug", NULL, "set-acl-entry/dw",
687 (intmax_t)dwResult);
688 goto fail;
691 d->pSD = (PSECURITY_DESCRIPTOR)LocalAlloc(
692 LPTR, SECURITY_DESCRIPTOR_MIN_LENGTH);
693 if (!InitializeSecurityDescriptor(d->pSD, SECURITY_DESCRIPTOR_REVISION)) {
694 DWORD gle = GetLastError();
695 trace2_data_intmax("ipc-debug", NULL, "init-sd/gle", (intmax_t)gle);
696 goto fail;
699 if (!SetSecurityDescriptorDacl(d->pSD, TRUE, d->pACL, FALSE)) {
700 DWORD gle = GetLastError();
701 trace2_data_intmax("ipc-debug", NULL, "set-sd-dacl/gle", (intmax_t)gle);
702 goto fail;
705 d->lpSA = (LPSECURITY_ATTRIBUTES)LocalAlloc(LPTR, sizeof(SECURITY_ATTRIBUTES));
706 d->lpSA->nLength = sizeof(SECURITY_ATTRIBUTES);
707 d->lpSA->lpSecurityDescriptor = d->pSD;
708 d->lpSA->bInheritHandle = FALSE;
710 return d->lpSA;
712 fail:
713 release_sa(d);
714 return NULL;
717 static HANDLE create_new_pipe(wchar_t *wpath, int is_first)
719 HANDLE hPipe;
720 DWORD dwOpenMode, dwPipeMode;
721 struct my_sa_data my_sa_data;
723 init_sa(&my_sa_data);
725 dwOpenMode = PIPE_ACCESS_INBOUND | PIPE_ACCESS_OUTBOUND |
726 FILE_FLAG_OVERLAPPED;
728 dwPipeMode = PIPE_TYPE_MESSAGE | PIPE_READMODE_BYTE | PIPE_WAIT |
729 PIPE_REJECT_REMOTE_CLIENTS;
731 if (is_first) {
732 dwOpenMode |= FILE_FLAG_FIRST_PIPE_INSTANCE;
735 * On Windows, the first server pipe instance gets to
736 * set the ACL / Security Attributes on the named
737 * pipe; subsequent instances inherit and cannot
738 * change them.
740 get_sa(&my_sa_data);
743 hPipe = CreateNamedPipeW(wpath, dwOpenMode, dwPipeMode,
744 PIPE_UNLIMITED_INSTANCES, 1024, 1024, 0,
745 my_sa_data.lpSA);
747 release_sa(&my_sa_data);
749 return hPipe;
752 int ipc_server_run_async(struct ipc_server_data **returned_server_data,
753 const char *path, const struct ipc_server_opts *opts,
754 ipc_server_application_cb *application_cb,
755 void *application_data)
757 struct ipc_server_data *server_data;
758 wchar_t wpath[MAX_PATH];
759 HANDLE hPipeFirst = INVALID_HANDLE_VALUE;
760 int k;
761 int ret = 0;
762 int nr_threads = opts->nr_threads;
764 *returned_server_data = NULL;
766 ret = initialize_pipe_name(path, wpath, ARRAY_SIZE(wpath));
767 if (ret < 0) {
768 errno = EINVAL;
769 return -1;
772 hPipeFirst = create_new_pipe(wpath, 1);
773 if (hPipeFirst == INVALID_HANDLE_VALUE) {
774 errno = EADDRINUSE;
775 return -2;
778 server_data = xcalloc(1, sizeof(*server_data));
779 server_data->magic = MAGIC_SERVER_DATA;
780 server_data->application_cb = application_cb;
781 server_data->application_data = application_data;
782 server_data->hEventStopRequested = CreateEvent(NULL, TRUE, FALSE, NULL);
783 strbuf_init(&server_data->buf_path, 0);
784 strbuf_addstr(&server_data->buf_path, path);
785 wcscpy(server_data->wpath, wpath);
787 if (nr_threads < 1)
788 nr_threads = 1;
790 for (k = 0; k < nr_threads; k++) {
791 struct ipc_server_thread_data *std;
793 std = xcalloc(1, sizeof(*std));
794 std->magic = MAGIC_SERVER_THREAD_DATA;
795 std->server_data = server_data;
796 std->hPipe = INVALID_HANDLE_VALUE;
798 std->hPipe = (k == 0)
799 ? hPipeFirst
800 : create_new_pipe(server_data->wpath, 0);
802 if (std->hPipe == INVALID_HANDLE_VALUE) {
804 * If we've reached a pipe instance limit for
805 * this path, just use fewer threads.
807 free(std);
808 break;
811 if (pthread_create(&std->pthread_id, NULL,
812 server_thread_proc, std)) {
814 * Likewise, if we're out of threads, just use
815 * fewer threads than requested.
817 * However, we just give up if we can't even get
818 * one thread. This should not happen.
820 if (k == 0)
821 die(_("could not start thread[0] for '%s'"),
822 path);
824 CloseHandle(std->hPipe);
825 free(std);
826 break;
829 std->next_thread = server_data->thread_list;
830 server_data->thread_list = std;
833 *returned_server_data = server_data;
834 return 0;
837 int ipc_server_stop_async(struct ipc_server_data *server_data)
839 if (!server_data)
840 return 0;
843 * Gently tell all of the ipc_server threads to shutdown.
844 * This will be seen the next time they are idle (and waiting
845 * for a connection).
847 * We DO NOT attempt to force them to drop an active connection.
849 SetEvent(server_data->hEventStopRequested);
850 return 0;
853 int ipc_server_await(struct ipc_server_data *server_data)
855 DWORD dwWaitResult;
857 if (!server_data)
858 return 0;
860 dwWaitResult = WaitForSingleObject(server_data->hEventStopRequested, INFINITE);
861 if (dwWaitResult != WAIT_OBJECT_0)
862 return error(_("wait for hEvent failed for '%s'"),
863 server_data->buf_path.buf);
865 while (server_data->thread_list) {
866 struct ipc_server_thread_data *std = server_data->thread_list;
868 pthread_join(std->pthread_id, NULL);
870 server_data->thread_list = std->next_thread;
871 free(std);
874 server_data->is_stopped = 1;
876 return 0;
879 void ipc_server_free(struct ipc_server_data *server_data)
881 if (!server_data)
882 return;
884 if (!server_data->is_stopped)
885 BUG("cannot free ipc-server while running for '%s'",
886 server_data->buf_path.buf);
888 strbuf_release(&server_data->buf_path);
890 if (server_data->hEventStopRequested != INVALID_HANDLE_VALUE)
891 CloseHandle(server_data->hEventStopRequested);
893 while (server_data->thread_list) {
894 struct ipc_server_thread_data *std = server_data->thread_list;
896 server_data->thread_list = std->next_thread;
897 free(std);
900 free(server_data);