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