2 * Copyright (C) 1996-2023 The Squid Software Foundation and contributors
4 * Squid software is distributed under GPLv2+ license and includes
5 * contributions from numerous individuals and organizations.
6 * Please see the COPYING and CONTRIBUTORS files for details.
9 /* DEBUG: section 54 Windows Interprocess Communication */
14 #include "comm/Connection.h"
18 #include "ip/Address.h"
20 #include "SquidConfig.h"
37 Ip::Address local_addr
;
43 struct thread_params
{
51 static unsigned int __stdcall
ipc_thread_1(void *params
);
52 static unsigned int __stdcall
ipc_thread_2(void *params
);
54 static const char *ok_string
= "OK\n";
55 static const char *err_string
= "ERR\n";
56 static const char *shutdown_string
= "$shutdown\n";
58 static const char *hello_string
= "hi there\n";
59 #define HELLO_BUF_SZ 32
60 static char hello_buf
[HELLO_BUF_SZ
];
63 ipcCloseAllFD(int prfd
, int pwfd
, int crfd
, int cwfd
)
88 env_str
= (char *)xcalloc((tmp_s
= strlen(Debug::debugOptions
) + 32), 1);
89 snprintf(env_str
, tmp_s
, "SQUID_DEBUG=%s", Debug::debugOptions
);
95 ipcCreate(int type
, const char *prog
, const char *const args
[], const char *name
, Ip::Address
&local_addr
, int *rfd
, int *wfd
, void **hIpc
)
99 struct ipc_params params
;
101 int optlen
= sizeof(opt
);
105 Ip::Address tmp_addr
;
106 struct addrinfo
*aiCS
= nullptr;
107 struct addrinfo
*aiPS
= nullptr;
115 requirePathnameExists(name
, prog
);
126 if (WIN32_OS_version
!= _WIN_OS_WINNT
) {
127 getsockopt(INVALID_SOCKET
, SOL_SOCKET
, SO_OPENTYPE
, (char *) &opt
, &optlen
);
128 opt
= opt
& ~(SO_SYNCHRONOUS_NONALERT
| SO_SYNCHRONOUS_ALERT
);
129 setsockopt(INVALID_SOCKET
, SOL_SOCKET
, SO_OPENTYPE
, (char *) &opt
, sizeof(opt
));
132 if (type
== IPC_TCP_SOCKET
) {
133 crfd
= cwfd
= comm_open_listener(SOCK_STREAM
,
138 prfd
= pwfd
= comm_open(SOCK_STREAM
,
139 IPPROTO_TCP
, /* protocol */
143 } else if (type
== IPC_UDP_SOCKET
) {
144 crfd
= cwfd
= comm_open(SOCK_DGRAM
,
149 prfd
= pwfd
= comm_open(SOCK_DGRAM
,
154 } else if (type
== IPC_FIFO
) {
155 debugs(54, DBG_CRITICAL
, "ipcCreate: " << prog
<< ": use IPC_TCP_SOCKET instead of IP_FIFO on Windows");
161 debugs(54, 3, "ipcCreate: prfd FD " << prfd
);
162 debugs(54, 3, "ipcCreate: pwfd FD " << pwfd
);
163 debugs(54, 3, "ipcCreate: crfd FD " << crfd
);
164 debugs(54, 3, "ipcCreate: cwfd FD " << cwfd
);
166 if (WIN32_OS_version
!= _WIN_OS_WINNT
) {
167 getsockopt(INVALID_SOCKET
, SOL_SOCKET
, SO_OPENTYPE
, (char *) &opt
, &optlen
);
168 opt
= opt
| SO_SYNCHRONOUS_NONALERT
;
169 setsockopt(INVALID_SOCKET
, SOL_SOCKET
, SO_OPENTYPE
, (char *) &opt
, optlen
);
173 debugs(54, DBG_CRITICAL
, "ERROR: ipcCreate: Failed to create child FD.");
174 return ipcCloseAllFD(prfd
, pwfd
, crfd
, cwfd
);
178 debugs(54, DBG_CRITICAL
, "ERROR: ipcCreate: Failed to create server FD.");
179 return ipcCloseAllFD(prfd
, pwfd
, crfd
, cwfd
);
182 // AYJ: these flags should be neutral, but if not IPv6 version needs adding
183 if (type
== IPC_TCP_SOCKET
|| type
== IPC_UDP_SOCKET
) {
185 Ip::Address::InitAddr(aiPS
);
187 if (getsockname(pwfd
, aiPS
->ai_addr
, &(aiPS
->ai_addrlen
) ) < 0) {
189 debugs(54, DBG_CRITICAL
, "ipcCreate: getsockname: " << xstrerr(xerrno
));
190 Ip::Address::FreeAddr(aiPS
);
191 return ipcCloseAllFD(prfd
, pwfd
, crfd
, cwfd
);
195 Ip::Address::FreeAddr(aiPS
);
197 debugs(54, 3, "ipcCreate: FD " << pwfd
<< " sockaddr " << tmp_addr
);
199 Ip::Address::InitAddr(aiCS
);
201 if (getsockname(crfd
, aiCS
->ai_addr
, &(aiCS
->ai_addrlen
) ) < 0) {
203 debugs(54, DBG_CRITICAL
, "ipcCreate: getsockname: " << xstrerr(xerrno
));
204 Ip::Address::FreeAddr(aiCS
);
205 return ipcCloseAllFD(prfd
, pwfd
, crfd
, cwfd
);
210 Ip::Address::FreeAddr(aiCS
);
212 debugs(54, 3, "ipcCreate: FD " << crfd
<< " sockaddr " << tmp_addr
);
215 if (type
== IPC_TCP_SOCKET
) {
216 if (listen(crfd
, 1) < 0) {
218 debugs(54, DBG_IMPORTANT
, "ipcCreate: listen FD " << crfd
<< ": " << xstrerr(xerrno
));
219 return ipcCloseAllFD(prfd
, pwfd
, crfd
, cwfd
);
222 debugs(54, 3, "ipcCreate: FD " << crfd
<< " listening...");
225 /* flush or else we get dup data if unbuffered_logs is set */
236 params
.local_addr
= local_addr
;
240 params
.args
= (char **) args
;
242 thread
= _beginthreadex(nullptr, 0, ipc_thread_1
, ¶ms
, 0, nullptr);
246 debugs(54, DBG_IMPORTANT
, "ipcCreate: _beginthread: " << xstrerr(xerrno
));
247 return ipcCloseAllFD(prfd
, pwfd
, crfd
, cwfd
);
250 /* NP: tmp_addr was left with eiether empty or aiCS in Ip::Address format */
251 if (comm_connect_addr(pwfd
, tmp_addr
) == Comm::COMM_ERROR
) {
252 CloseHandle((HANDLE
) thread
);
253 return ipcCloseAllFD(prfd
, pwfd
, -1, -1);
256 memset(hello_buf
, '\0', HELLO_BUF_SZ
);
257 x
= recv(prfd
, (void *)hello_buf
, HELLO_BUF_SZ
- 1, 0);
261 debugs(54, DBG_CRITICAL
, "ERROR: ipcCreate: PARENT: hello read test failed");
262 debugs(54, DBG_CRITICAL
, "--> read: " << xstrerr(xerrno
));
263 CloseHandle((HANDLE
) thread
);
264 return ipcCloseAllFD(prfd
, pwfd
, -1, -1);
265 } else if (strcmp(hello_buf
, hello_string
)) {
266 debugs(54, DBG_CRITICAL
, "ERROR: ipcCreate: PARENT: hello read test failed");
267 debugs(54, DBG_CRITICAL
, "--> read returned " << x
);
268 debugs(54, DBG_CRITICAL
, "--> got '" << rfc1738_escape(hello_buf
) << "'");
269 CloseHandle((HANDLE
) thread
);
270 return ipcCloseAllFD(prfd
, pwfd
, -1, -1);
273 x
= send(pwfd
, (const void *)ok_string
, strlen(ok_string
), 0);
277 debugs(54, DBG_CRITICAL
, "ERROR: ipcCreate: PARENT: OK write test failed");
278 debugs(54, DBG_CRITICAL
, "--> read: " << xstrerr(xerrno
));
279 CloseHandle((HANDLE
) thread
);
280 return ipcCloseAllFD(prfd
, pwfd
, -1, -1);
283 memset(hello_buf
, '\0', HELLO_BUF_SZ
);
284 x
= recv(prfd
, (void *)hello_buf
, HELLO_BUF_SZ
- 1, 0);
288 debugs(54, DBG_CRITICAL
, "ERROR: ipcCreate: PARENT: OK read test failed");
289 debugs(54, DBG_CRITICAL
, "--> read: " << xstrerr(xerrno
));
290 CloseHandle((HANDLE
) thread
);
291 return ipcCloseAllFD(prfd
, pwfd
, -1, -1);
292 } else if (!strcmp(hello_buf
, err_string
)) {
293 debugs(54, DBG_CRITICAL
, "ERROR: ipcCreate: PARENT: OK read test failed");
294 debugs(54, DBG_CRITICAL
, "--> read returned " << x
);
295 debugs(54, DBG_CRITICAL
, "--> got '" << rfc1738_escape(hello_buf
) << "'");
296 CloseHandle((HANDLE
) thread
);
297 return ipcCloseAllFD(prfd
, pwfd
, -1, -1);
301 pid
= atol(hello_buf
);
302 commUnsetFdTimeout(prfd
);
303 commSetNonBlocking(prfd
);
304 commSetNonBlocking(pwfd
);
305 commSetCloseOnExec(prfd
);
306 commSetCloseOnExec(pwfd
);
314 fd_table
[prfd
].flags
.ipc
= true;
315 fd_table
[pwfd
].flags
.ipc
= true;
316 fd_table
[crfd
].flags
.ipc
= true;
317 fd_table
[cwfd
].flags
.ipc
= true;
319 if (Config
.sleep_after_fork
)
320 std::this_thread::sleep_for(std::chrono::microseconds(Config
.sleep_after_fork
));
322 if (GetExitCodeThread((HANDLE
) thread
, &ecode
) && ecode
== STILL_ACTIVE
) {
324 *hIpc
= (HANDLE
) thread
;
328 CloseHandle((HANDLE
) thread
);
329 return ipcCloseAllFD(prfd
, pwfd
, -1, -1);
334 ipcSend(int cwfd
, const char *buf
, int len
)
336 int x
= send(cwfd
, (const void *)buf
, len
, 0);
340 debugs(54, DBG_CRITICAL
, "sendto FD " << cwfd
<< ": " << xstrerr(xerrno
));
341 debugs(54, DBG_CRITICAL
, "ERROR: ipcCreate: CHILD: hello write test failed");
347 static unsigned int __stdcall
348 ipc_thread_1(void *in_params
)
350 int t1
, t2
, t3
, retval
= -1;
351 int p2c
[2] = {-1, -1};
352 int c2p
[2] = {-1, -1};
353 HANDLE hProcess
= nullptr, thread
= nullptr;
356 struct thread_params thread_params
;
361 PROCESS_INFORMATION pi
;
363 int prfd_ipc
= -1, pwfd_ipc
= -1, crfd_ipc
= -1, cwfd_ipc
= -1;
364 char *prog
= nullptr, *buf1
= nullptr;
368 struct addrinfo
*aiPS_ipc
= nullptr;
369 struct addrinfo
*aiCS_ipc
= nullptr;
371 struct ipc_params
*params
= (struct ipc_params
*) in_params
;
372 int type
= params
->type
;
373 int crfd
= params
->crfd
;
374 int cwfd
= params
->cwfd
;
375 char **args
= params
->args
;
377 Ip::Address PS
= params
->PS
;
378 Ip::Address local_addr
= params
->local_addr
;
380 const size_t bufSz
= 8192;
381 buf1
= (char *)xcalloc(1, bufSz
);
382 strcpy(buf1
, params
->prog
);
383 prog
= strtok(buf1
, w_space
);
385 if ((str
= strrchr(prog
, '/')))
388 if ((str
= strrchr(prog
, '\\')))
391 prog
= xstrdup(prog
);
393 if (type
== IPC_TCP_SOCKET
) {
394 debugs(54, 3, "ipcCreate: calling accept on FD " << crfd
);
396 if ((fd
= accept(crfd
, nullptr, nullptr)) < 0) {
398 debugs(54, DBG_CRITICAL
, "ipcCreate: FD " << crfd
<< " accept: " << xstrerr(xerrno
));
402 debugs(54, 3, "ipcCreate: CHILD accepted new FD " << fd
);
404 snprintf(buf1
, bufSz
-1, "%s CHILD socket", prog
);
405 fd_open(fd
, FD_SOCKET
, buf1
);
406 fd_table
[fd
].flags
.ipc
= 1;
408 } else if (type
== IPC_UDP_SOCKET
) {
409 if (comm_connect_addr(crfd
, params
->PS
) == Comm::COMM_ERROR
)
413 x
= send(cwfd
, (const void *)hello_string
, strlen(hello_string
) + 1, 0);
417 debugs(54, DBG_CRITICAL
, "sendto FD " << cwfd
<< ": " << xstrerr(xerrno
));
418 debugs(54, DBG_CRITICAL
, "ERROR: ipcCreate: CHILD: hello write test failed");
423 memset(buf1
, '\0', bufSz
);
424 x
= recv(crfd
, (void *)buf1
, bufSz
-1, 0);
428 debugs(54, DBG_CRITICAL
, "ERROR: ipcCreate: CHILD: OK read test failed");
429 debugs(54, DBG_CRITICAL
, "--> read: " << xstrerr(xerrno
));
431 } else if (strcmp(buf1
, ok_string
)) {
432 debugs(54, DBG_CRITICAL
, "ERROR: ipcCreate: CHILD: OK read test failed");
433 debugs(54, DBG_CRITICAL
, "--> read returned " << x
);
434 debugs(54, DBG_CRITICAL
, "--> got '" << rfc1738_escape(hello_buf
) << "'");
438 /* assign file descriptors to child process */
439 if (_pipe(p2c
, 1024, _O_BINARY
| _O_NOINHERIT
) < 0) {
441 debugs(54, DBG_CRITICAL
, "ipcCreate: CHILD: pipe: " << xstrerr(xerrno
));
442 ipcSend(cwfd
, err_string
, strlen(err_string
));
446 if (_pipe(c2p
, 1024, _O_BINARY
| _O_NOINHERIT
) < 0) {
448 debugs(54, DBG_CRITICAL
, "ipcCreate: CHILD: pipe: " << xstrerr(xerrno
));
449 ipcSend(cwfd
, err_string
, strlen(err_string
));
453 if (type
== IPC_UDP_SOCKET
) {
454 snprintf(buf1
, bufSz
, "%s(%ld) <-> ipc CHILD socket", prog
, -1L);
455 crfd_ipc
= cwfd_ipc
= comm_open(SOCK_DGRAM
, IPPROTO_UDP
, local_addr
, 0, buf1
);
458 debugs(54, DBG_CRITICAL
, "ERROR: ipcCreate: CHILD: Failed to create child FD for " << prog
<< ".");
459 ipcSend(cwfd
, err_string
, strlen(err_string
));
463 snprintf(buf1
, bufSz
, "%s(%ld) <-> ipc PARENT socket", prog
, -1L);
464 prfd_ipc
= pwfd_ipc
= comm_open(SOCK_DGRAM
, IPPROTO_UDP
, local_addr
, 0, buf1
);
467 debugs(54, DBG_CRITICAL
, "ERROR: ipcCreate: CHILD: Failed to create server FD for " << prog
<< ".");
468 ipcSend(cwfd
, err_string
, strlen(err_string
));
472 Ip::Address::InitAddr(aiPS_ipc
);
474 if (getsockname(pwfd_ipc
, aiPS_ipc
->ai_addr
, &(aiPS_ipc
->ai_addrlen
)) < 0) {
476 debugs(54, DBG_CRITICAL
, "ipcCreate: getsockname: " << xstrerr(xerrno
));
477 ipcSend(cwfd
, err_string
, strlen(err_string
));
478 Ip::Address::FreeAddr(aiPS_ipc
);
483 Ip::Address::FreeAddr(aiPS_ipc
);
485 debugs(54, 3, "ipcCreate: FD " << pwfd_ipc
<< " sockaddr " << PS_ipc
);
487 Ip::Address::InitAddr(aiCS_ipc
);
489 if (getsockname(crfd_ipc
, aiCS_ipc
->ai_addr
, &(aiCS_ipc
->ai_addrlen
)) < 0) {
491 debugs(54, DBG_CRITICAL
, "ipcCreate: getsockname: " << xstrerr(xerrno
));
492 ipcSend(cwfd
, err_string
, strlen(err_string
));
493 Ip::Address::FreeAddr(aiCS_ipc
);
498 Ip::Address::FreeAddr(aiCS_ipc
);
500 debugs(54, 3, "ipcCreate: FD " << crfd_ipc
<< " sockaddr " << CS_ipc
);
502 if (comm_connect_addr(pwfd_ipc
, CS_ipc
) == Comm::COMM_ERROR
) {
503 ipcSend(cwfd
, err_string
, strlen(err_string
));
509 if (comm_connect_addr(crfd_ipc
, PS_ipc
) == Comm::COMM_ERROR
) {
510 ipcSend(cwfd
, err_string
, strlen(err_string
));
513 } /* IPC_UDP_SOCKET */
525 dup2(fileno(debug_log
), 2);
531 commUnsetNonBlocking(fd
);
533 memset(&si
, 0, sizeof(STARTUPINFO
));
535 si
.cb
= sizeof(STARTUPINFO
);
537 si
.hStdInput
= (HANDLE
) _get_osfhandle(0);
539 si
.hStdOutput
= (HANDLE
) _get_osfhandle(1);
541 si
.hStdError
= (HANDLE
) _get_osfhandle(2);
543 si
.dwFlags
= STARTF_USESTDHANDLES
;
545 /* Make sure all other valid handles are not inerithable */
546 for (x
= 3; x
< Squid_MaxFD
; ++x
) {
547 if ((F
= _get_osfhandle(x
)) == -1)
550 SetHandleInformation((HANDLE
) F
, HANDLE_FLAG_INHERIT
, 0);
554 strcpy(buf1
+ 4096, params
->prog
);
555 str
= strtok(buf1
+ 4096, w_space
);
560 } while ((str
= strtok(nullptr, w_space
)));
565 strcat(buf1
, args
[x
]);
570 if (CreateProcess(buf1
+ 4096, buf1
, nullptr, nullptr, TRUE
, CREATE_NO_WINDOW
,
571 nullptr, nullptr, &si
, &pi
)) {
572 pid
= pi
.dwProcessId
;
573 hProcess
= pi
.hProcess
;
587 debugs(54, DBG_CRITICAL
, "ipcCreate: CHILD: " << params
->prog
<< ": " << xstrerr(x
));
589 ipcSend(cwfd
, err_string
, strlen(err_string
));
593 if (type
== IPC_UDP_SOCKET
) {
594 WSAPROTOCOL_INFO wpi
;
596 memset(&wpi
, 0, sizeof(wpi
));
598 if (SOCKET_ERROR
== WSADuplicateSocket(crfd_ipc
, pid
, &wpi
)) {
600 debugs(54, DBG_CRITICAL
, "ipcCreate: CHILD: WSADuplicateSocket: " << xstrerr(xerrno
));
601 ipcSend(cwfd
, err_string
, strlen(err_string
));
605 x
= write(c2p
[1], (const char *) &wpi
, sizeof(wpi
));
607 if (x
< (ssize_t
)sizeof(wpi
)) {
609 debugs(54, DBG_CRITICAL
, "ipcCreate: CHILD: write FD " << c2p
[1] << ": " << xstrerr(xerrno
));
610 debugs(54, DBG_CRITICAL
, "ERROR: ipcCreate: CHILD: " << prog
<< ": socket exchange failed");
611 ipcSend(cwfd
, err_string
, strlen(err_string
));
615 x
= read(p2c
[0], buf1
, bufSz
-1);
619 debugs(54, DBG_CRITICAL
, "ipcCreate: CHILD: read FD " << p2c
[0] << ": " << xstrerr(xerrno
));
620 debugs(54, DBG_CRITICAL
, "ERROR: ipcCreate: CHILD: " << prog
<< ": socket exchange failed");
621 ipcSend(cwfd
, err_string
, strlen(err_string
));
623 } else if (strncmp(buf1
, ok_string
, strlen(ok_string
))) {
624 debugs(54, DBG_CRITICAL
, "ERROR: ipcCreate: CHILD: " << prog
<< ": socket exchange failed");
625 debugs(54, DBG_CRITICAL
, "--> read returned " << x
);
627 debugs(54, DBG_CRITICAL
, "--> got '" << rfc1738_escape(buf1
) << "'");
628 ipcSend(cwfd
, err_string
, strlen(err_string
));
632 x
= write(c2p
[1], (const char *) &PS_ipc
, sizeof(PS_ipc
));
634 if (x
< (ssize_t
)sizeof(PS_ipc
)) {
636 debugs(54, DBG_CRITICAL
, "ipcCreate: CHILD: write FD " << c2p
[1] << ": " << xstrerr(xerrno
));
637 debugs(54, DBG_CRITICAL
, "ERROR: ipcCreate: CHILD: " << prog
<< ": socket exchange failed");
638 ipcSend(cwfd
, err_string
, strlen(err_string
));
642 x
= read(p2c
[0], buf1
, bufSz
-1);
646 debugs(54, DBG_CRITICAL
, "ipcCreate: CHILD: read FD " << p2c
[0] << ": " << xstrerr(xerrno
));
647 debugs(54, DBG_CRITICAL
, "ERROR: ipcCreate: CHILD: " << prog
<< ": socket exchange failed");
648 ipcSend(cwfd
, err_string
, strlen(err_string
));
650 } else if (strncmp(buf1
, ok_string
, strlen(ok_string
))) {
651 debugs(54, DBG_CRITICAL
, "ERROR: ipcCreate: CHILD: " << prog
<< ": socket exchange failed");
652 debugs(54, DBG_CRITICAL
, "--> read returned " << x
);
654 debugs(54, DBG_CRITICAL
, "--> got '" << rfc1738_escape(buf1
) << "'");
655 ipcSend(cwfd
, err_string
, strlen(err_string
));
659 x
= send(pwfd_ipc
, (const void *)ok_string
, strlen(ok_string
), 0);
660 x
= recv(prfd_ipc
, (void *)(buf1
+ 200), bufSz
-1 - 200, 0);
661 assert((size_t) x
== strlen(ok_string
)
662 && !strncmp(ok_string
, buf1
+ 200, strlen(ok_string
)));
663 } /* IPC_UDP_SOCKET */
665 snprintf(buf1
, bufSz
-1, "%s(%ld) CHILD socket", prog
, (long int) pid
);
669 if (prfd_ipc
!= -1) {
670 snprintf(buf1
, bufSz
-1, "%s(%ld) <-> ipc CHILD socket", prog
, (long int) pid
);
671 fd_note(crfd_ipc
, buf1
);
672 snprintf(buf1
, bufSz
-1, "%s(%ld) <-> ipc PARENT socket", prog
, (long int) pid
);
673 fd_note(prfd_ipc
, buf1
);
676 /* else { IPC_TCP_SOCKET */
677 /* commSetNoLinger(fd); */
679 thread_params
.prog
= prog
;
681 thread_params
.send_fd
= cwfd
;
683 thread_params
.pid
= pid
;
685 if ((thread_params
.type
= type
) == IPC_TCP_SOCKET
)
686 thread_params
.rfd
= p2c
[0];
688 thread_params
.rfd
= prfd_ipc
;
690 thread
= (HANDLE
)_beginthreadex(nullptr, 0, ipc_thread_2
, &thread_params
, 0, nullptr);
694 debugs(54, DBG_CRITICAL
, "ipcCreate: CHILD: _beginthreadex: " << xstrerr(xerrno
));
695 ipcSend(cwfd
, err_string
, strlen(err_string
));
699 snprintf(buf1
, bufSz
-1, "%ld\n", (long int) pid
);
701 if (-1 == ipcSend(cwfd
, buf1
, strlen(buf1
)))
704 debugs(54, 2, "ipc(" << prog
<< "," << pid
<< "): started successfully");
708 x
= recv(crfd
, (void *)buf1
, bufSz
-1, 0);
711 debugs(54, 3, "ipc(" << prog
<< "," << pid
<< "): " << x
<< " bytes received from parent. Exiting...");
717 if (type
== IPC_UDP_SOCKET
&& !strcmp(buf1
, shutdown_string
)) {
718 debugs(54, 3, "ipc(" << prog
<< "," << pid
<< "): request for shutdown received from parent. Exiting...");
720 TerminateProcess(hProcess
, 0);
724 debugs(54, 5, "ipc(" << prog
<< "," << pid
<< "): received from parent: " << rfc1738_escape_unescaped(buf1
));
726 if (type
== IPC_TCP_SOCKET
)
727 x
= write(c2p
[1], buf1
, x
);
729 x
= send(pwfd_ipc
, (const void *)buf1
, x
, 0);
732 debugs(54, 3, "ipc(" << prog
<< "," << pid
<< "): " << x
<< " bytes written to " << prog
<< ". Exiting...");
745 if (fd_table
[crfd
].flags
.open
)
746 ipcCloseAllFD(-1, -1, crfd
, cwfd
);
748 if (prfd_ipc
!= -1) {
749 send(crfd_ipc
, (const void *)shutdown_string
, strlen(shutdown_string
), 0);
750 shutdown(crfd_ipc
, SD_BOTH
);
751 shutdown(prfd_ipc
, SD_BOTH
);
754 ipcCloseAllFD(prfd_ipc
, pwfd_ipc
, crfd_ipc
, cwfd_ipc
);
756 if (hProcess
&& WAIT_OBJECT_0
!=
757 WaitForSingleObject(hProcess
, type
== IPC_UDP_SOCKET
? 12000 : 5000)) {
760 debugs(54, DBG_CRITICAL
, "ipc(" << prog
<< "," << pid
<< "): WARNING: " << prog
<<
761 " didn't exit in " << (type
== IPC_UDP_SOCKET
? 12 : 5) << " seconds.");
765 if (thread
&& WAIT_OBJECT_0
!= WaitForSingleObject(thread
, 3000)) {
767 debugs(54, DBG_CRITICAL
, "ipc(" << prog
<< "," << pid
<< "): WARNING: ipc_thread_2 didn't exit in 3 seconds.");
774 debugs(54, 2, "ipc(" << prog
<< "," << pid
<< "): normal exit");
783 CloseHandle(hProcess
);
791 static unsigned int __stdcall
792 ipc_thread_2(void *in_params
)
796 struct thread_params
*params
= (struct thread_params
*) in_params
;
797 int type
= params
->type
;
798 int rfd
= params
->rfd
;
799 int send_fd
= params
->send_fd
;
800 char *prog
= xstrdup(params
->prog
);
801 pid_t pid
= params
->pid
;
802 const size_t bufSz
= 8192;
803 char *buf2
= (char *)xcalloc(1, bufSz
);
806 if (type
== IPC_TCP_SOCKET
)
807 x
= read(rfd
, buf2
, bufSz
-1);
809 x
= recv(rfd
, (void *)buf2
, bufSz
-1, 0);
811 if ((x
<= 0 && type
== IPC_TCP_SOCKET
) ||
812 (x
< 0 && type
== IPC_UDP_SOCKET
)) {
813 debugs(54, 3, "ipc(" << prog
<< "," << pid
<< "): " << x
<< " bytes read from " << prog
<< ". Exiting...");
820 if (type
== IPC_UDP_SOCKET
&& !strcmp(buf2
, shutdown_string
)) {
821 debugs(54, 3, "ipc(" << prog
<< "," << pid
<< "): request for shutdown received. Exiting...");
826 if ((buf2
[x
- 1] == '\n') && (buf2
[x
- 2] == '\r')) {
833 debugs(54, 5, "ipc(" << prog
<< "," << pid
<< "): received from child : " << rfc1738_escape_unescaped(buf2
));
835 x
= send(send_fd
, (const void *)buf2
, x
, 0);
837 if ((x
<= 0 && type
== IPC_TCP_SOCKET
) ||
838 (x
< 0 && type
== IPC_UDP_SOCKET
)) {
839 debugs(54, 3, "ipc(" << prog
<< "," << pid
<< "): " << x
<< " bytes sent to parent. Exiting...");