]> git.ipfire.org Git - thirdparty/git.git/blob - compat/simple-ipc/ipc-win32.c
treewide: be explicit about dependence on trace.h & trace2.h
[thirdparty/git.git] / compat / simple-ipc / ipc-win32.c
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 "trace.h"
9 #include "trace2.h"
10 #include "accctrl.h"
11 #include "aclapi.h"
12
13 #ifndef SUPPORTS_SIMPLE_IPC
14 /*
15 * This source file should only be compiled when Simple IPC is supported.
16 * See the top-level Makefile.
17 */
18 #error SUPPORTS_SIMPLE_IPC not defined
19 #endif
20
21 static int initialize_pipe_name(const char *path, wchar_t *wpath, size_t alloc)
22 {
23 int off = 0;
24 struct strbuf realpath = STRBUF_INIT;
25
26 if (!strbuf_realpath(&realpath, path, 0))
27 return -1;
28
29 off = swprintf(wpath, alloc, L"\\\\.\\pipe\\");
30 if (xutftowcs(wpath + off, realpath.buf, alloc - off) < 0)
31 return -1;
32
33 /* Handle drive prefix */
34 if (wpath[off] && wpath[off + 1] == L':') {
35 wpath[off + 1] = L'_';
36 off += 2;
37 }
38
39 for (; wpath[off]; off++)
40 if (wpath[off] == L'/')
41 wpath[off] = L'\\';
42
43 strbuf_release(&realpath);
44 return 0;
45 }
46
47 static enum ipc_active_state get_active_state(wchar_t *pipe_path)
48 {
49 if (WaitNamedPipeW(pipe_path, NMPWAIT_USE_DEFAULT_WAIT))
50 return IPC_STATE__LISTENING;
51
52 if (GetLastError() == ERROR_SEM_TIMEOUT)
53 return IPC_STATE__NOT_LISTENING;
54
55 if (GetLastError() == ERROR_FILE_NOT_FOUND)
56 return IPC_STATE__PATH_NOT_FOUND;
57
58 trace2_data_intmax("ipc-debug", NULL, "getstate/waitpipe/gle",
59 (intmax_t)GetLastError());
60
61 return IPC_STATE__OTHER_ERROR;
62 }
63
64 enum ipc_active_state ipc_get_active_state(const char *path)
65 {
66 wchar_t pipe_path[MAX_PATH];
67
68 if (initialize_pipe_name(path, pipe_path, ARRAY_SIZE(pipe_path)) < 0)
69 return IPC_STATE__INVALID_PATH;
70
71 return get_active_state(pipe_path);
72 }
73
74 #define WAIT_STEP_MS (50)
75
76 static enum ipc_active_state connect_to_server(
77 const wchar_t *wpath,
78 DWORD timeout_ms,
79 const struct ipc_client_connect_options *options,
80 int *pfd)
81 {
82 DWORD t_start_ms, t_waited_ms;
83 DWORD step_ms;
84 HANDLE hPipe = INVALID_HANDLE_VALUE;
85 DWORD mode = PIPE_READMODE_BYTE;
86 DWORD gle;
87
88 *pfd = -1;
89
90 for (;;) {
91 hPipe = CreateFileW(wpath, GENERIC_READ | GENERIC_WRITE,
92 0, NULL, OPEN_EXISTING, 0, NULL);
93 if (hPipe != INVALID_HANDLE_VALUE)
94 break;
95
96 gle = GetLastError();
97
98 switch (gle) {
99 case ERROR_FILE_NOT_FOUND:
100 if (!options->wait_if_not_found)
101 return IPC_STATE__PATH_NOT_FOUND;
102 if (!timeout_ms)
103 return IPC_STATE__PATH_NOT_FOUND;
104
105 step_ms = (timeout_ms < WAIT_STEP_MS) ?
106 timeout_ms : WAIT_STEP_MS;
107 sleep_millisec(step_ms);
108
109 timeout_ms -= step_ms;
110 break; /* try again */
111
112 case ERROR_PIPE_BUSY:
113 if (!options->wait_if_busy)
114 return IPC_STATE__NOT_LISTENING;
115 if (!timeout_ms)
116 return IPC_STATE__NOT_LISTENING;
117
118 t_start_ms = (DWORD)(getnanotime() / 1000000);
119
120 if (!WaitNamedPipeW(wpath, timeout_ms)) {
121 DWORD gleWait = GetLastError();
122
123 if (gleWait == ERROR_SEM_TIMEOUT)
124 return IPC_STATE__NOT_LISTENING;
125
126 trace2_data_intmax("ipc-debug", NULL,
127 "connect/waitpipe/gle",
128 (intmax_t)gleWait);
129
130 return IPC_STATE__OTHER_ERROR;
131 }
132
133 /*
134 * A pipe server instance became available.
135 * Race other client processes to connect to
136 * it.
137 *
138 * But first decrement our overall timeout so
139 * that we don't starve if we keep losing the
140 * race. But also guard against special
141 * NPMWAIT_ values (0 and -1).
142 */
143 t_waited_ms = (DWORD)(getnanotime() / 1000000) - t_start_ms;
144 if (t_waited_ms < timeout_ms)
145 timeout_ms -= t_waited_ms;
146 else
147 timeout_ms = 1;
148 break; /* try again */
149
150 default:
151 trace2_data_intmax("ipc-debug", NULL,
152 "connect/createfile/gle",
153 (intmax_t)gle);
154
155 return IPC_STATE__OTHER_ERROR;
156 }
157 }
158
159 if (!SetNamedPipeHandleState(hPipe, &mode, NULL, NULL)) {
160 gle = GetLastError();
161 trace2_data_intmax("ipc-debug", NULL,
162 "connect/setpipestate/gle",
163 (intmax_t)gle);
164
165 CloseHandle(hPipe);
166 return IPC_STATE__OTHER_ERROR;
167 }
168
169 *pfd = _open_osfhandle((intptr_t)hPipe, O_RDWR|O_BINARY);
170 if (*pfd < 0) {
171 gle = GetLastError();
172 trace2_data_intmax("ipc-debug", NULL,
173 "connect/openosfhandle/gle",
174 (intmax_t)gle);
175
176 CloseHandle(hPipe);
177 return IPC_STATE__OTHER_ERROR;
178 }
179
180 /* fd now owns hPipe */
181
182 return IPC_STATE__LISTENING;
183 }
184
185 /*
186 * The default connection timeout for Windows clients.
187 *
188 * This is not currently part of the ipc_ API (nor the config settings)
189 * because of differences between Windows and other platforms.
190 *
191 * This value was chosen at random.
192 */
193 #define WINDOWS_CONNECTION_TIMEOUT_MS (30000)
194
195 enum ipc_active_state ipc_client_try_connect(
196 const char *path,
197 const struct ipc_client_connect_options *options,
198 struct ipc_client_connection **p_connection)
199 {
200 wchar_t wpath[MAX_PATH];
201 enum ipc_active_state state = IPC_STATE__OTHER_ERROR;
202 int fd = -1;
203
204 *p_connection = NULL;
205
206 trace2_region_enter("ipc-client", "try-connect", NULL);
207 trace2_data_string("ipc-client", NULL, "try-connect/path", path);
208
209 if (initialize_pipe_name(path, wpath, ARRAY_SIZE(wpath)) < 0)
210 state = IPC_STATE__INVALID_PATH;
211 else
212 state = connect_to_server(wpath, WINDOWS_CONNECTION_TIMEOUT_MS,
213 options, &fd);
214
215 trace2_data_intmax("ipc-client", NULL, "try-connect/state",
216 (intmax_t)state);
217 trace2_region_leave("ipc-client", "try-connect", NULL);
218
219 if (state == IPC_STATE__LISTENING) {
220 (*p_connection) = xcalloc(1, sizeof(struct ipc_client_connection));
221 (*p_connection)->fd = fd;
222 }
223
224 return state;
225 }
226
227 void ipc_client_close_connection(struct ipc_client_connection *connection)
228 {
229 if (!connection)
230 return;
231
232 if (connection->fd != -1)
233 close(connection->fd);
234
235 free(connection);
236 }
237
238 int ipc_client_send_command_to_connection(
239 struct ipc_client_connection *connection,
240 const char *message, size_t message_len,
241 struct strbuf *answer)
242 {
243 int ret = 0;
244
245 strbuf_setlen(answer, 0);
246
247 trace2_region_enter("ipc-client", "send-command", NULL);
248
249 if (write_packetized_from_buf_no_flush(message, message_len,
250 connection->fd) < 0 ||
251 packet_flush_gently(connection->fd) < 0) {
252 ret = error(_("could not send IPC command"));
253 goto done;
254 }
255
256 FlushFileBuffers((HANDLE)_get_osfhandle(connection->fd));
257
258 if (read_packetized_to_strbuf(
259 connection->fd, answer,
260 PACKET_READ_GENTLE_ON_EOF | PACKET_READ_GENTLE_ON_READ_ERROR) < 0) {
261 ret = error(_("could not read IPC response"));
262 goto done;
263 }
264
265 done:
266 trace2_region_leave("ipc-client", "send-command", NULL);
267 return ret;
268 }
269
270 int ipc_client_send_command(const char *path,
271 const struct ipc_client_connect_options *options,
272 const char *message, size_t message_len,
273 struct strbuf *response)
274 {
275 int ret = -1;
276 enum ipc_active_state state;
277 struct ipc_client_connection *connection = NULL;
278
279 state = ipc_client_try_connect(path, options, &connection);
280
281 if (state != IPC_STATE__LISTENING)
282 return ret;
283
284 ret = ipc_client_send_command_to_connection(connection,
285 message, message_len,
286 response);
287
288 ipc_client_close_connection(connection);
289
290 return ret;
291 }
292
293 /*
294 * Duplicate the given pipe handle and wrap it in a file descriptor so
295 * that we can use pkt-line on it.
296 */
297 static int dup_fd_from_pipe(const HANDLE pipe)
298 {
299 HANDLE process = GetCurrentProcess();
300 HANDLE handle;
301 int fd;
302
303 if (!DuplicateHandle(process, pipe, process, &handle, 0, FALSE,
304 DUPLICATE_SAME_ACCESS)) {
305 errno = err_win_to_posix(GetLastError());
306 return -1;
307 }
308
309 fd = _open_osfhandle((intptr_t)handle, O_RDWR|O_BINARY);
310 if (fd < 0) {
311 errno = err_win_to_posix(GetLastError());
312 CloseHandle(handle);
313 return -1;
314 }
315
316 /*
317 * `handle` is now owned by `fd` and will be automatically closed
318 * when the descriptor is closed.
319 */
320
321 return fd;
322 }
323
324 /*
325 * Magic numbers used to annotate callback instance data.
326 * These are used to help guard against accidentally passing the
327 * wrong instance data across multiple levels of callbacks (which
328 * is easy to do if there are `void*` arguments).
329 */
330 enum magic {
331 MAGIC_SERVER_REPLY_DATA,
332 MAGIC_SERVER_THREAD_DATA,
333 MAGIC_SERVER_DATA,
334 };
335
336 struct ipc_server_reply_data {
337 enum magic magic;
338 int fd;
339 struct ipc_server_thread_data *server_thread_data;
340 };
341
342 struct ipc_server_thread_data {
343 enum magic magic;
344 struct ipc_server_thread_data *next_thread;
345 struct ipc_server_data *server_data;
346 pthread_t pthread_id;
347 HANDLE hPipe;
348 };
349
350 /*
351 * On Windows, the conceptual "ipc-server" is implemented as a pool of
352 * n idential/peer "server-thread" threads. That is, there is no
353 * hierarchy of threads; and therefore no controller thread managing
354 * the pool. Each thread has an independent handle to the named pipe,
355 * receives incoming connections, processes the client, and re-uses
356 * the pipe for the next client connection.
357 *
358 * Therefore, the "ipc-server" only needs to maintain a list of the
359 * spawned threads for eventual "join" purposes.
360 *
361 * A single "stop-event" is visible to all of the server threads to
362 * tell them to shutdown (when idle).
363 */
364 struct ipc_server_data {
365 enum magic magic;
366 ipc_server_application_cb *application_cb;
367 void *application_data;
368 struct strbuf buf_path;
369 wchar_t wpath[MAX_PATH];
370
371 HANDLE hEventStopRequested;
372 struct ipc_server_thread_data *thread_list;
373 int is_stopped;
374 };
375
376 enum connect_result {
377 CR_CONNECTED = 0,
378 CR_CONNECT_PENDING,
379 CR_CONNECT_ERROR,
380 CR_WAIT_ERROR,
381 CR_SHUTDOWN,
382 };
383
384 static enum connect_result queue_overlapped_connect(
385 struct ipc_server_thread_data *server_thread_data,
386 OVERLAPPED *lpo)
387 {
388 if (ConnectNamedPipe(server_thread_data->hPipe, lpo))
389 goto failed;
390
391 switch (GetLastError()) {
392 case ERROR_IO_PENDING:
393 return CR_CONNECT_PENDING;
394
395 case ERROR_PIPE_CONNECTED:
396 SetEvent(lpo->hEvent);
397 return CR_CONNECTED;
398
399 default:
400 break;
401 }
402
403 failed:
404 error(_("ConnectNamedPipe failed for '%s' (%lu)"),
405 server_thread_data->server_data->buf_path.buf,
406 GetLastError());
407 return CR_CONNECT_ERROR;
408 }
409
410 /*
411 * Use Windows Overlapped IO to wait for a connection or for our event
412 * to be signalled.
413 */
414 static enum connect_result wait_for_connection(
415 struct ipc_server_thread_data *server_thread_data,
416 OVERLAPPED *lpo)
417 {
418 enum connect_result r;
419 HANDLE waitHandles[2];
420 DWORD dwWaitResult;
421
422 r = queue_overlapped_connect(server_thread_data, lpo);
423 if (r != CR_CONNECT_PENDING)
424 return r;
425
426 waitHandles[0] = server_thread_data->server_data->hEventStopRequested;
427 waitHandles[1] = lpo->hEvent;
428
429 dwWaitResult = WaitForMultipleObjects(2, waitHandles, FALSE, INFINITE);
430 switch (dwWaitResult) {
431 case WAIT_OBJECT_0 + 0:
432 return CR_SHUTDOWN;
433
434 case WAIT_OBJECT_0 + 1:
435 ResetEvent(lpo->hEvent);
436 return CR_CONNECTED;
437
438 default:
439 return CR_WAIT_ERROR;
440 }
441 }
442
443 /*
444 * Forward declare our reply callback function so that any compiler
445 * errors are reported when we actually define the function (in addition
446 * to any errors reported when we try to pass this callback function as
447 * a parameter in a function call). The former are easier to understand.
448 */
449 static ipc_server_reply_cb do_io_reply_callback;
450
451 /*
452 * Relay application's response message to the client process.
453 * (We do not flush at this point because we allow the caller
454 * to chunk data to the client thru us.)
455 */
456 static int do_io_reply_callback(struct ipc_server_reply_data *reply_data,
457 const char *response, size_t response_len)
458 {
459 if (reply_data->magic != MAGIC_SERVER_REPLY_DATA)
460 BUG("reply_cb called with wrong instance data");
461
462 return write_packetized_from_buf_no_flush(response, response_len,
463 reply_data->fd);
464 }
465
466 /*
467 * Receive the request/command from the client and pass it to the
468 * registered request-callback. The request-callback will compose
469 * a response and call our reply-callback to send it to the client.
470 *
471 * Simple-IPC only contains one round trip, so we flush and close
472 * here after the response.
473 */
474 static int do_io(struct ipc_server_thread_data *server_thread_data)
475 {
476 struct strbuf buf = STRBUF_INIT;
477 struct ipc_server_reply_data reply_data;
478 int ret = 0;
479
480 reply_data.magic = MAGIC_SERVER_REPLY_DATA;
481 reply_data.server_thread_data = server_thread_data;
482
483 reply_data.fd = dup_fd_from_pipe(server_thread_data->hPipe);
484 if (reply_data.fd < 0)
485 return error(_("could not create fd from pipe for '%s'"),
486 server_thread_data->server_data->buf_path.buf);
487
488 ret = read_packetized_to_strbuf(
489 reply_data.fd, &buf,
490 PACKET_READ_GENTLE_ON_EOF | PACKET_READ_GENTLE_ON_READ_ERROR);
491 if (ret >= 0) {
492 ret = server_thread_data->server_data->application_cb(
493 server_thread_data->server_data->application_data,
494 buf.buf, buf.len, do_io_reply_callback, &reply_data);
495
496 packet_flush_gently(reply_data.fd);
497
498 FlushFileBuffers((HANDLE)_get_osfhandle((reply_data.fd)));
499 }
500 else {
501 /*
502 * The client probably disconnected/shutdown before it
503 * could send a well-formed message. Ignore it.
504 */
505 }
506
507 strbuf_release(&buf);
508 close(reply_data.fd);
509
510 return ret;
511 }
512
513 /*
514 * Handle IPC request and response with this connected client. And reset
515 * the pipe to prepare for the next client.
516 */
517 static int use_connection(struct ipc_server_thread_data *server_thread_data)
518 {
519 int ret;
520
521 ret = do_io(server_thread_data);
522
523 FlushFileBuffers(server_thread_data->hPipe);
524 DisconnectNamedPipe(server_thread_data->hPipe);
525
526 return ret;
527 }
528
529 /*
530 * Thread proc for an IPC server worker thread. It handles a series of
531 * connections from clients. It cleans and reuses the hPipe between each
532 * client.
533 */
534 static void *server_thread_proc(void *_server_thread_data)
535 {
536 struct ipc_server_thread_data *server_thread_data = _server_thread_data;
537 HANDLE hEventConnected = INVALID_HANDLE_VALUE;
538 OVERLAPPED oConnect;
539 enum connect_result cr;
540 int ret;
541
542 assert(server_thread_data->hPipe != INVALID_HANDLE_VALUE);
543
544 trace2_thread_start("ipc-server");
545 trace2_data_string("ipc-server", NULL, "pipe",
546 server_thread_data->server_data->buf_path.buf);
547
548 hEventConnected = CreateEventW(NULL, TRUE, FALSE, NULL);
549
550 memset(&oConnect, 0, sizeof(oConnect));
551 oConnect.hEvent = hEventConnected;
552
553 for (;;) {
554 cr = wait_for_connection(server_thread_data, &oConnect);
555
556 switch (cr) {
557 case CR_SHUTDOWN:
558 goto finished;
559
560 case CR_CONNECTED:
561 ret = use_connection(server_thread_data);
562 if (ret == SIMPLE_IPC_QUIT) {
563 ipc_server_stop_async(
564 server_thread_data->server_data);
565 goto finished;
566 }
567 if (ret > 0) {
568 /*
569 * Ignore (transient) IO errors with this
570 * client and reset for the next client.
571 */
572 }
573 break;
574
575 case CR_CONNECT_PENDING:
576 /* By construction, this should not happen. */
577 BUG("ipc-server[%s]: unexpeced CR_CONNECT_PENDING",
578 server_thread_data->server_data->buf_path.buf);
579
580 case CR_CONNECT_ERROR:
581 case CR_WAIT_ERROR:
582 /*
583 * Ignore these theoretical errors.
584 */
585 DisconnectNamedPipe(server_thread_data->hPipe);
586 break;
587
588 default:
589 BUG("unandled case after wait_for_connection");
590 }
591 }
592
593 finished:
594 CloseHandle(server_thread_data->hPipe);
595 CloseHandle(hEventConnected);
596
597 trace2_thread_exit();
598 return NULL;
599 }
600
601 /*
602 * We need to build a Windows "SECURITY_ATTRIBUTES" object and use it
603 * to apply an ACL when we create the initial instance of the Named
604 * Pipe. The construction is somewhat involved and consists of
605 * several sequential steps and intermediate objects.
606 *
607 * We use this structure to hold these intermediate pointers so that
608 * we can free them as a group. (It is unclear from the docs whether
609 * some of these intermediate pointers can be freed before we are
610 * finished using the "lpSA" member.)
611 */
612 struct my_sa_data
613 {
614 PSID pEveryoneSID;
615 PACL pACL;
616 PSECURITY_DESCRIPTOR pSD;
617 LPSECURITY_ATTRIBUTES lpSA;
618 };
619
620 static void init_sa(struct my_sa_data *d)
621 {
622 memset(d, 0, sizeof(*d));
623 }
624
625 static void release_sa(struct my_sa_data *d)
626 {
627 if (d->pEveryoneSID)
628 FreeSid(d->pEveryoneSID);
629 if (d->pACL)
630 LocalFree(d->pACL);
631 if (d->pSD)
632 LocalFree(d->pSD);
633 if (d->lpSA)
634 LocalFree(d->lpSA);
635
636 memset(d, 0, sizeof(*d));
637 }
638
639 /*
640 * Create SECURITY_ATTRIBUTES to apply to the initial named pipe. The
641 * creator of the first server instance gets to set the ACLs on it.
642 *
643 * We allow the well-known group `EVERYONE` to have read+write access
644 * to the named pipe so that clients can send queries to the daemon
645 * and receive the response.
646 *
647 * Normally, this is not necessary since the daemon is usually
648 * automatically started by a foreground command like `git status`,
649 * but in those cases where an elevated Git command started the daemon
650 * (such that the daemon itself runs with elevation), we need to add
651 * the ACL so that non-elevated commands can write to it.
652 *
653 * The following document was helpful:
654 * https://docs.microsoft.com/en-us/windows/win32/secauthz/creating-a-security-descriptor-for-a-new-object-in-c--
655 *
656 * Returns d->lpSA set to a SA or NULL.
657 */
658 static LPSECURITY_ATTRIBUTES get_sa(struct my_sa_data *d)
659 {
660 SID_IDENTIFIER_AUTHORITY sid_auth_world = SECURITY_WORLD_SID_AUTHORITY;
661 #define NR_EA (1)
662 EXPLICIT_ACCESS ea[NR_EA];
663 DWORD dwResult;
664
665 if (!AllocateAndInitializeSid(&sid_auth_world, 1,
666 SECURITY_WORLD_RID, 0,0,0,0,0,0,0,
667 &d->pEveryoneSID)) {
668 DWORD gle = GetLastError();
669 trace2_data_intmax("ipc-debug", NULL, "alloc-world-sid/gle",
670 (intmax_t)gle);
671 goto fail;
672 }
673
674 memset(ea, 0, NR_EA * sizeof(EXPLICIT_ACCESS));
675
676 ea[0].grfAccessPermissions = GENERIC_READ | GENERIC_WRITE;
677 ea[0].grfAccessMode = SET_ACCESS;
678 ea[0].grfInheritance = NO_INHERITANCE;
679 ea[0].Trustee.MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
680 ea[0].Trustee.TrusteeForm = TRUSTEE_IS_SID;
681 ea[0].Trustee.TrusteeType = TRUSTEE_IS_WELL_KNOWN_GROUP;
682 ea[0].Trustee.ptstrName = (LPTSTR)d->pEveryoneSID;
683
684 dwResult = SetEntriesInAcl(NR_EA, ea, NULL, &d->pACL);
685 if (dwResult != ERROR_SUCCESS) {
686 DWORD gle = GetLastError();
687 trace2_data_intmax("ipc-debug", NULL, "set-acl-entry/gle",
688 (intmax_t)gle);
689 trace2_data_intmax("ipc-debug", NULL, "set-acl-entry/dw",
690 (intmax_t)dwResult);
691 goto fail;
692 }
693
694 d->pSD = (PSECURITY_DESCRIPTOR)LocalAlloc(
695 LPTR, SECURITY_DESCRIPTOR_MIN_LENGTH);
696 if (!InitializeSecurityDescriptor(d->pSD, SECURITY_DESCRIPTOR_REVISION)) {
697 DWORD gle = GetLastError();
698 trace2_data_intmax("ipc-debug", NULL, "init-sd/gle", (intmax_t)gle);
699 goto fail;
700 }
701
702 if (!SetSecurityDescriptorDacl(d->pSD, TRUE, d->pACL, FALSE)) {
703 DWORD gle = GetLastError();
704 trace2_data_intmax("ipc-debug", NULL, "set-sd-dacl/gle", (intmax_t)gle);
705 goto fail;
706 }
707
708 d->lpSA = (LPSECURITY_ATTRIBUTES)LocalAlloc(LPTR, sizeof(SECURITY_ATTRIBUTES));
709 d->lpSA->nLength = sizeof(SECURITY_ATTRIBUTES);
710 d->lpSA->lpSecurityDescriptor = d->pSD;
711 d->lpSA->bInheritHandle = FALSE;
712
713 return d->lpSA;
714
715 fail:
716 release_sa(d);
717 return NULL;
718 }
719
720 static HANDLE create_new_pipe(wchar_t *wpath, int is_first)
721 {
722 HANDLE hPipe;
723 DWORD dwOpenMode, dwPipeMode;
724 struct my_sa_data my_sa_data;
725
726 init_sa(&my_sa_data);
727
728 dwOpenMode = PIPE_ACCESS_INBOUND | PIPE_ACCESS_OUTBOUND |
729 FILE_FLAG_OVERLAPPED;
730
731 dwPipeMode = PIPE_TYPE_MESSAGE | PIPE_READMODE_BYTE | PIPE_WAIT |
732 PIPE_REJECT_REMOTE_CLIENTS;
733
734 if (is_first) {
735 dwOpenMode |= FILE_FLAG_FIRST_PIPE_INSTANCE;
736
737 /*
738 * On Windows, the first server pipe instance gets to
739 * set the ACL / Security Attributes on the named
740 * pipe; subsequent instances inherit and cannot
741 * change them.
742 */
743 get_sa(&my_sa_data);
744 }
745
746 hPipe = CreateNamedPipeW(wpath, dwOpenMode, dwPipeMode,
747 PIPE_UNLIMITED_INSTANCES, 1024, 1024, 0,
748 my_sa_data.lpSA);
749
750 release_sa(&my_sa_data);
751
752 return hPipe;
753 }
754
755 int ipc_server_run_async(struct ipc_server_data **returned_server_data,
756 const char *path, const struct ipc_server_opts *opts,
757 ipc_server_application_cb *application_cb,
758 void *application_data)
759 {
760 struct ipc_server_data *server_data;
761 wchar_t wpath[MAX_PATH];
762 HANDLE hPipeFirst = INVALID_HANDLE_VALUE;
763 int k;
764 int ret = 0;
765 int nr_threads = opts->nr_threads;
766
767 *returned_server_data = NULL;
768
769 ret = initialize_pipe_name(path, wpath, ARRAY_SIZE(wpath));
770 if (ret < 0) {
771 errno = EINVAL;
772 return -1;
773 }
774
775 hPipeFirst = create_new_pipe(wpath, 1);
776 if (hPipeFirst == INVALID_HANDLE_VALUE) {
777 errno = EADDRINUSE;
778 return -2;
779 }
780
781 server_data = xcalloc(1, sizeof(*server_data));
782 server_data->magic = MAGIC_SERVER_DATA;
783 server_data->application_cb = application_cb;
784 server_data->application_data = application_data;
785 server_data->hEventStopRequested = CreateEvent(NULL, TRUE, FALSE, NULL);
786 strbuf_init(&server_data->buf_path, 0);
787 strbuf_addstr(&server_data->buf_path, path);
788 wcscpy(server_data->wpath, wpath);
789
790 if (nr_threads < 1)
791 nr_threads = 1;
792
793 for (k = 0; k < nr_threads; k++) {
794 struct ipc_server_thread_data *std;
795
796 std = xcalloc(1, sizeof(*std));
797 std->magic = MAGIC_SERVER_THREAD_DATA;
798 std->server_data = server_data;
799 std->hPipe = INVALID_HANDLE_VALUE;
800
801 std->hPipe = (k == 0)
802 ? hPipeFirst
803 : create_new_pipe(server_data->wpath, 0);
804
805 if (std->hPipe == INVALID_HANDLE_VALUE) {
806 /*
807 * If we've reached a pipe instance limit for
808 * this path, just use fewer threads.
809 */
810 free(std);
811 break;
812 }
813
814 if (pthread_create(&std->pthread_id, NULL,
815 server_thread_proc, std)) {
816 /*
817 * Likewise, if we're out of threads, just use
818 * fewer threads than requested.
819 *
820 * However, we just give up if we can't even get
821 * one thread. This should not happen.
822 */
823 if (k == 0)
824 die(_("could not start thread[0] for '%s'"),
825 path);
826
827 CloseHandle(std->hPipe);
828 free(std);
829 break;
830 }
831
832 std->next_thread = server_data->thread_list;
833 server_data->thread_list = std;
834 }
835
836 *returned_server_data = server_data;
837 return 0;
838 }
839
840 int ipc_server_stop_async(struct ipc_server_data *server_data)
841 {
842 if (!server_data)
843 return 0;
844
845 /*
846 * Gently tell all of the ipc_server threads to shutdown.
847 * This will be seen the next time they are idle (and waiting
848 * for a connection).
849 *
850 * We DO NOT attempt to force them to drop an active connection.
851 */
852 SetEvent(server_data->hEventStopRequested);
853 return 0;
854 }
855
856 int ipc_server_await(struct ipc_server_data *server_data)
857 {
858 DWORD dwWaitResult;
859
860 if (!server_data)
861 return 0;
862
863 dwWaitResult = WaitForSingleObject(server_data->hEventStopRequested, INFINITE);
864 if (dwWaitResult != WAIT_OBJECT_0)
865 return error(_("wait for hEvent failed for '%s'"),
866 server_data->buf_path.buf);
867
868 while (server_data->thread_list) {
869 struct ipc_server_thread_data *std = server_data->thread_list;
870
871 pthread_join(std->pthread_id, NULL);
872
873 server_data->thread_list = std->next_thread;
874 free(std);
875 }
876
877 server_data->is_stopped = 1;
878
879 return 0;
880 }
881
882 void ipc_server_free(struct ipc_server_data *server_data)
883 {
884 if (!server_data)
885 return;
886
887 if (!server_data->is_stopped)
888 BUG("cannot free ipc-server while running for '%s'",
889 server_data->buf_path.buf);
890
891 strbuf_release(&server_data->buf_path);
892
893 if (server_data->hEventStopRequested != INVALID_HANDLE_VALUE)
894 CloseHandle(server_data->hEventStopRequested);
895
896 while (server_data->thread_list) {
897 struct ipc_server_thread_data *std = server_data->thread_list;
898
899 server_data->thread_list = std->next_thread;
900 free(std);
901 }
902
903 free(server_data);
904 }