2 * DEBUG: section 54 Windows Interprocess Communication
3 * AUTHOR: Andrey Shorin <tolsty@tushino.com>
4 * AUTHOR: Guido Serassio <serassio@squid-cache.org>
6 * SQUID Web Proxy Cache http://www.squid-cache.org/
7 * ----------------------------------------------------------
9 * Squid is the result of efforts by numerous individuals from
10 * the Internet community; see the CONTRIBUTORS file for full
11 * details. Many organizations have provided support for Squid's
12 * development; see the SPONSORS file for full details. Squid is
13 * Copyrighted (C) 2001 by the Regents of the University of
14 * California; see the COPYRIGHT file for full details. Squid
15 * incorporates software developed and/or copyrighted by other
16 * sources; see the CREDITS file for full details.
18 * This program is free software; you can redistribute it and/or modify
19 * it under the terms of the GNU General Public License as published by
20 * the Free Software Foundation; either version 2 of the License, or
21 * (at your option) any later version.
23 * This program is distributed in the hope that it will be useful,
24 * but WITHOUT ANY WARRANTY; without even the implied warranty of
25 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
26 * GNU General Public License for more details.
28 * You should have received a copy of the GNU General Public License
29 * along with this program; if not, write to the Free Software
30 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
39 #include "ip/Address.h"
41 #include "SquidConfig.h"
43 #include "SquidTime.h"
56 Ip::Address local_addr
;
62 struct thread_params
{
70 static unsigned int __stdcall
ipc_thread_1(void *params
);
71 static unsigned int __stdcall
ipc_thread_2(void *params
);
73 static const char *ok_string
= "OK\n";
74 static const char *err_string
= "ERR\n";
75 static const char *shutdown_string
= "$shutdown\n";
77 static const char *hello_string
= "hi there\n";
78 #define HELLO_BUF_SZ 32
79 static char hello_buf
[HELLO_BUF_SZ
];
82 ipcCloseAllFD(int prfd
, int pwfd
, int crfd
, int cwfd
)
107 env_str
= (char *)xcalloc((tmp_s
= strlen(Debug::debugOptions
) + 32), 1);
108 snprintf(env_str
, tmp_s
, "SQUID_DEBUG=%s", Debug::debugOptions
);
114 ipcCreate(int type
, const char *prog
, const char *const args
[], const char *name
, Ip::Address
&local_addr
, int *rfd
, int *wfd
, void **hIpc
)
116 unsigned long thread
;
118 struct ipc_params params
;
120 int optlen
= sizeof(opt
);
124 Ip::Address tmp_addr
;
125 struct addrinfo
*aiCS
= NULL
;
126 struct addrinfo
*aiPS
= NULL
;
134 requirePathnameExists(name
, prog
);
145 if (WIN32_OS_version
!= _WIN_OS_WINNT
) {
146 getsockopt(INVALID_SOCKET
, SOL_SOCKET
, SO_OPENTYPE
, (char *) &opt
, &optlen
);
147 opt
= opt
& ~(SO_SYNCHRONOUS_NONALERT
| SO_SYNCHRONOUS_ALERT
);
148 setsockopt(INVALID_SOCKET
, SOL_SOCKET
, SO_OPENTYPE
, (char *) &opt
, sizeof(opt
));
151 if (type
== IPC_TCP_SOCKET
) {
152 crfd
= cwfd
= comm_open(SOCK_STREAM
,
157 prfd
= pwfd
= comm_open(SOCK_STREAM
,
158 IPPROTO_TCP
, /* protocol */
162 } else if (type
== IPC_UDP_SOCKET
) {
163 crfd
= cwfd
= comm_open(SOCK_DGRAM
,
168 prfd
= pwfd
= comm_open(SOCK_DGRAM
,
173 } else if (type
== IPC_FIFO
) {
174 debugs(54, DBG_CRITICAL
, "ipcCreate: " << prog
<< ": use IPC_TCP_SOCKET instead of IP_FIFO on Windows");
180 debugs(54, 3, "ipcCreate: prfd FD " << prfd
);
181 debugs(54, 3, "ipcCreate: pwfd FD " << pwfd
);
182 debugs(54, 3, "ipcCreate: crfd FD " << crfd
);
183 debugs(54, 3, "ipcCreate: cwfd FD " << cwfd
);
185 if (WIN32_OS_version
!= _WIN_OS_WINNT
) {
186 getsockopt(INVALID_SOCKET
, SOL_SOCKET
, SO_OPENTYPE
, (char *) &opt
, &optlen
);
187 opt
= opt
| SO_SYNCHRONOUS_NONALERT
;
188 setsockopt(INVALID_SOCKET
, SOL_SOCKET
, SO_OPENTYPE
, (char *) &opt
, optlen
);
192 debugs(54, DBG_CRITICAL
, "ipcCreate: Failed to create child FD.");
193 return ipcCloseAllFD(prfd
, pwfd
, crfd
, cwfd
);
197 debugs(54, DBG_CRITICAL
, "ipcCreate: Failed to create server FD.");
198 return ipcCloseAllFD(prfd
, pwfd
, crfd
, cwfd
);
201 // AYJ: these flags should be neutral, but if not IPv6 version needs adding
202 if (type
== IPC_TCP_SOCKET
|| type
== IPC_UDP_SOCKET
) {
204 Ip::Address::InitAddrInfo(aiPS
);
206 if (getsockname(pwfd
, aiPS
->ai_addr
, &(aiPS
->ai_addrlen
) ) < 0) {
207 debugs(54, DBG_CRITICAL
, "ipcCreate: getsockname: " << xstrerror());
208 Ip::Address::FreeAddrInfo(aiPS
);
209 return ipcCloseAllFD(prfd
, pwfd
, crfd
, cwfd
);
213 Ip::Address::FreeAddrInfo(aiPS
);
215 debugs(54, 3, "ipcCreate: FD " << pwfd
<< " sockaddr " << tmp_addr
);
217 Ip::Address::InitAddrInfo(aiCS
);
219 if (getsockname(crfd
, aiCS
->ai_addr
, &(aiCS
->ai_addrlen
) ) < 0) {
220 debugs(54, DBG_CRITICAL
, "ipcCreate: getsockname: " << xstrerror());
221 Ip::Address::FreeAddrInfo(aiCS
);
222 return ipcCloseAllFD(prfd
, pwfd
, crfd
, cwfd
);
227 Ip::Address::FreeAddrInfo(aiCS
);
229 debugs(54, 3, "ipcCreate: FD " << crfd
<< " sockaddr " << tmp_addr
);
232 if (type
== IPC_TCP_SOCKET
) {
233 if (listen(crfd
, 1) < 0) {
234 debugs(54, DBG_IMPORTANT
, "ipcCreate: listen FD " << crfd
<< ": " << xstrerror());
235 return ipcCloseAllFD(prfd
, pwfd
, crfd
, cwfd
);
238 debugs(54, 3, "ipcCreate: FD " << crfd
<< " listening...");
241 /* flush or else we get dup data if unbuffered_logs is set */
252 params
.local_addr
= local_addr
;
256 params
.args
= (char **) args
;
258 thread
= _beginthreadex(NULL
, 0, ipc_thread_1
, ¶ms
, 0, NULL
);
261 debugs(54, DBG_IMPORTANT
, "ipcCreate: _beginthread: " << xstrerror());
262 return ipcCloseAllFD(prfd
, pwfd
, crfd
, cwfd
);
265 /* NP: tmp_addr was left with eiether empty or aiCS in Ip::Address format */
266 if (comm_connect_addr(pwfd
, tmp_addr
) == Comm::COMM_ERROR
) {
267 CloseHandle((HANDLE
) thread
);
268 return ipcCloseAllFD(prfd
, pwfd
, -1, -1);
271 memset(hello_buf
, '\0', HELLO_BUF_SZ
);
272 x
= recv(prfd
, (void *)hello_buf
, HELLO_BUF_SZ
- 1, 0);
275 debugs(54, DBG_CRITICAL
, "ipcCreate: PARENT: hello read test failed");
276 debugs(54, DBG_CRITICAL
, "--> read: " << xstrerror());
277 CloseHandle((HANDLE
) thread
);
278 return ipcCloseAllFD(prfd
, pwfd
, -1, -1);
279 } else if (strcmp(hello_buf
, hello_string
)) {
280 debugs(54, DBG_CRITICAL
, "ipcCreate: PARENT: hello read test failed");
281 debugs(54, DBG_CRITICAL
, "--> read returned " << x
);
282 debugs(54, DBG_CRITICAL
, "--> got '" << rfc1738_escape(hello_buf
) << "'");
283 CloseHandle((HANDLE
) thread
);
284 return ipcCloseAllFD(prfd
, pwfd
, -1, -1);
287 x
= send(pwfd
, (const void *)ok_string
, strlen(ok_string
), 0);
290 debugs(54, DBG_CRITICAL
, "ipcCreate: PARENT: OK write test failed");
291 debugs(54, DBG_CRITICAL
, "--> read: " << xstrerror());
292 CloseHandle((HANDLE
) thread
);
293 return ipcCloseAllFD(prfd
, pwfd
, -1, -1);
296 memset(hello_buf
, '\0', HELLO_BUF_SZ
);
297 x
= recv(prfd
, (void *)hello_buf
, HELLO_BUF_SZ
- 1, 0);
300 debugs(54, DBG_CRITICAL
, "ipcCreate: PARENT: OK read test failed");
301 debugs(54, DBG_CRITICAL
, "--> read: " << xstrerror());
302 CloseHandle((HANDLE
) thread
);
303 return ipcCloseAllFD(prfd
, pwfd
, -1, -1);
304 } else if (!strcmp(hello_buf
, err_string
)) {
305 debugs(54, DBG_CRITICAL
, "ipcCreate: PARENT: OK read test failed");
306 debugs(54, DBG_CRITICAL
, "--> read returned " << x
);
307 debugs(54, DBG_CRITICAL
, "--> got '" << rfc1738_escape(hello_buf
) << "'");
308 CloseHandle((HANDLE
) thread
);
309 return ipcCloseAllFD(prfd
, pwfd
, -1, -1);
313 pid
= atol(hello_buf
);
314 commUnsetFdTimeout(prfd
);
315 commSetNonBlocking(prfd
);
316 commSetNonBlocking(pwfd
);
317 commSetCloseOnExec(prfd
);
318 commSetCloseOnExec(pwfd
);
326 fd_table
[prfd
].flags
.ipc
= true;
327 fd_table
[pwfd
].flags
.ipc
= true;
328 fd_table
[crfd
].flags
.ipc
= true;
329 fd_table
[cwfd
].flags
.ipc
= true;
331 if (Config
.sleep_after_fork
) {
332 /* XXX emulation of usleep() */
334 sl
= Config
.sleep_after_fork
/ 1000;
342 if (GetExitCodeThread((HANDLE
) thread
, &ecode
) && ecode
== STILL_ACTIVE
) {
344 *hIpc
= (HANDLE
) thread
;
348 CloseHandle((HANDLE
) thread
);
349 return ipcCloseAllFD(prfd
, pwfd
, -1, -1);
354 ipcSend(int cwfd
, const char *buf
, int len
)
358 x
= send(cwfd
, (const void *)buf
, len
, 0);
361 debugs(54, DBG_CRITICAL
, "sendto FD " << cwfd
<< ": " << xstrerror());
362 debugs(54, DBG_CRITICAL
, "ipcCreate: CHILD: hello write test failed");
368 static unsigned int __stdcall
369 ipc_thread_1(void *in_params
)
371 int t1
, t2
, t3
, retval
= -1;
372 int p2c
[2] = {-1, -1};
373 int c2p
[2] = {-1, -1};
374 HANDLE hProcess
= NULL
, thread
= NULL
;
377 struct thread_params thread_params
;
382 PROCESS_INFORMATION pi
;
384 int prfd_ipc
= -1, pwfd_ipc
= -1, crfd_ipc
= -1, cwfd_ipc
= -1;
385 char *prog
= NULL
, *buf1
= NULL
;
389 struct addrinfo
*aiPS_ipc
= NULL
;
390 struct addrinfo
*aiCS_ipc
= NULL
;
392 struct ipc_params
*params
= (struct ipc_params
*) in_params
;
393 int type
= params
->type
;
394 int crfd
= params
->crfd
;
395 int cwfd
= params
->cwfd
;
396 char **args
= params
->args
;
398 Ip::Address PS
= params
->PS
;
399 Ip::Address local_addr
= params
->local_addr
;
401 buf1
= (char *)xcalloc(1, 8192);
402 strcpy(buf1
, params
->prog
);
403 prog
= strtok(buf1
, w_space
);
405 if ((str
= strrchr(prog
, '/')))
408 if ((str
= strrchr(prog
, '\\')))
411 prog
= xstrdup(prog
);
413 if (type
== IPC_TCP_SOCKET
) {
414 debugs(54, 3, "ipcCreate: calling accept on FD " << crfd
);
416 if ((fd
= accept(crfd
, NULL
, NULL
)) < 0) {
417 debugs(54, DBG_CRITICAL
, "ipcCreate: FD " << crfd
<< " accept: " << xstrerror());
421 debugs(54, 3, "ipcCreate: CHILD accepted new FD " << fd
);
423 snprintf(buf1
, 8191, "%s CHILD socket", prog
);
424 fd_open(fd
, FD_SOCKET
, buf1
);
425 fd_table
[fd
].flags
.ipc
= 1;
427 } else if (type
== IPC_UDP_SOCKET
) {
428 if (comm_connect_addr(crfd
, params
->PS
) == Comm::COMM_ERROR
)
432 x
= send(cwfd
, (const void *)hello_string
, strlen(hello_string
) + 1, 0);
435 debugs(54, DBG_CRITICAL
, "sendto FD " << cwfd
<< ": " << xstrerror());
436 debugs(54, DBG_CRITICAL
, "ipcCreate: CHILD: hello write test failed");
441 memset(buf1
, '\0', sizeof(buf1
));
442 x
= recv(crfd
, (void *)buf1
, 8191, 0);
445 debugs(54, DBG_CRITICAL
, "ipcCreate: CHILD: OK read test failed");
446 debugs(54, DBG_CRITICAL
, "--> read: " << xstrerror());
448 } else if (strcmp(buf1
, ok_string
)) {
449 debugs(54, DBG_CRITICAL
, "ipcCreate: CHILD: OK read test failed");
450 debugs(54, DBG_CRITICAL
, "--> read returned " << x
);
451 debugs(54, DBG_CRITICAL
, "--> got '" << rfc1738_escape(hello_buf
) << "'");
455 /* assign file descriptors to child process */
456 if (_pipe(p2c
, 1024, _O_BINARY
| _O_NOINHERIT
) < 0) {
457 debugs(54, DBG_CRITICAL
, "ipcCreate: CHILD: pipe: " << xstrerror());
458 ipcSend(cwfd
, err_string
, strlen(err_string
));
462 if (_pipe(c2p
, 1024, _O_BINARY
| _O_NOINHERIT
) < 0) {
463 debugs(54, DBG_CRITICAL
, "ipcCreate: CHILD: pipe: " << xstrerror());
464 ipcSend(cwfd
, err_string
, strlen(err_string
));
468 if (type
== IPC_UDP_SOCKET
) {
469 snprintf(buf1
, 8192, "%s(%ld) <-> ipc CHILD socket", prog
, -1L);
470 crfd_ipc
= cwfd_ipc
= comm_open(SOCK_DGRAM
, IPPROTO_UDP
, local_addr
, 0, buf1
);
473 debugs(54, DBG_CRITICAL
, "ipcCreate: CHILD: Failed to create child FD for " << prog
<< ".");
474 ipcSend(cwfd
, err_string
, strlen(err_string
));
478 snprintf(buf1
, 8192, "%s(%ld) <-> ipc PARENT socket", prog
, -1L);
479 prfd_ipc
= pwfd_ipc
= comm_open(SOCK_DGRAM
, IPPROTO_UDP
, local_addr
, 0, buf1
);
482 debugs(54, DBG_CRITICAL
, "ipcCreate: CHILD: Failed to create server FD for " << prog
<< ".");
483 ipcSend(cwfd
, err_string
, strlen(err_string
));
487 Ip::Address::InitAddrInfo(aiPS_ipc
);
489 if (getsockname(pwfd_ipc
, aiPS_ipc
->ai_addr
, &(aiPS_ipc
->ai_addrlen
)) < 0) {
490 debugs(54, DBG_CRITICAL
, "ipcCreate: getsockname: " << xstrerror());
491 ipcSend(cwfd
, err_string
, strlen(err_string
));
492 Ip::Address::FreeAddrInfo(aiPS_ipc
);
497 Ip::Address::FreeAddrInfo(aiPS_ipc
);
499 debugs(54, 3, "ipcCreate: FD " << pwfd_ipc
<< " sockaddr " << PS_ipc
);
501 Ip::Address::InitAddrInfo(aiCS_ipc
);
503 if (getsockname(crfd_ipc
, aiCS_ipc
->ai_addr
, &(aiCS_ipc
->ai_addrlen
)) < 0) {
504 debugs(54, DBG_CRITICAL
, "ipcCreate: getsockname: " << xstrerror());
505 ipcSend(cwfd
, err_string
, strlen(err_string
));
506 Ip::Address::FreeAddrInfo(aiCS_ipc
);
511 Ip::Address::FreeAddrInfo(aiCS_ipc
);
513 debugs(54, 3, "ipcCreate: FD " << crfd_ipc
<< " sockaddr " << CS_ipc
);
515 if (comm_connect_addr(pwfd_ipc
, CS_ipc
) == Comm::COMM_ERROR
) {
516 ipcSend(cwfd
, err_string
, strlen(err_string
));
522 if (comm_connect_addr(crfd_ipc
, PS_ipc
) == Comm::COMM_ERROR
) {
523 ipcSend(cwfd
, err_string
, strlen(err_string
));
526 } /* IPC_UDP_SOCKET */
538 dup2(fileno(debug_log
), 2);
544 commUnsetNonBlocking(fd
);
546 memset(&si
, 0, sizeof(STARTUPINFO
));
548 si
.cb
= sizeof(STARTUPINFO
);
550 si
.hStdInput
= (HANDLE
) _get_osfhandle(0);
552 si
.hStdOutput
= (HANDLE
) _get_osfhandle(1);
554 si
.hStdError
= (HANDLE
) _get_osfhandle(2);
556 si
.dwFlags
= STARTF_USESTDHANDLES
;
558 /* Make sure all other valid handles are not inerithable */
559 for (x
= 3; x
< Squid_MaxFD
; ++x
) {
560 if ((F
= _get_osfhandle(x
)) == -1)
563 SetHandleInformation((HANDLE
) F
, HANDLE_FLAG_INHERIT
, 0);
567 strcpy(buf1
+ 4096, params
->prog
);
568 str
= strtok(buf1
+ 4096, w_space
);
573 } while ((str
= strtok(NULL
, w_space
)));
578 strcat(buf1
, args
[x
]);
583 if (CreateProcess(buf1
+ 4096, buf1
, NULL
, NULL
, TRUE
, CREATE_NO_WINDOW
,
584 NULL
, NULL
, &si
, &pi
)) {
585 pid
= pi
.dwProcessId
;
586 hProcess
= pi
.hProcess
;
601 debugs(54, DBG_CRITICAL
, "ipcCreate: CHILD: " << params
->prog
<< ": " << xstrerror());
603 ipcSend(cwfd
, err_string
, strlen(err_string
));
607 if (type
== IPC_UDP_SOCKET
) {
608 WSAPROTOCOL_INFO wpi
;
610 memset(&wpi
, 0, sizeof(wpi
));
612 if (SOCKET_ERROR
== WSADuplicateSocket(crfd_ipc
, pid
, &wpi
)) {
613 debugs(54, DBG_CRITICAL
, "ipcCreate: CHILD: WSADuplicateSocket: " << xstrerror());
615 ipcSend(cwfd
, err_string
, strlen(err_string
));
619 x
= write(c2p
[1], (const char *) &wpi
, sizeof(wpi
));
621 if (x
< (ssize_t
)sizeof(wpi
)) {
622 debugs(54, DBG_CRITICAL
, "ipcCreate: CHILD: write FD " << c2p
[1] << ": " << xstrerror());
623 debugs(54, DBG_CRITICAL
, "ipcCreate: CHILD: " << prog
<< ": socket exchange failed");
625 ipcSend(cwfd
, err_string
, strlen(err_string
));
629 x
= read(p2c
[0], buf1
, 8192);
632 debugs(54, DBG_CRITICAL
, "ipcCreate: CHILD: read FD " << p2c
[0] << ": " << xstrerror());
633 debugs(54, DBG_CRITICAL
, "ipcCreate: CHILD: " << prog
<< ": socket exchange failed");
635 ipcSend(cwfd
, err_string
, strlen(err_string
));
637 } else if (strncmp(buf1
, ok_string
, strlen(ok_string
))) {
638 debugs(54, DBG_CRITICAL
, "ipcCreate: CHILD: " << prog
<< ": socket exchange failed");
639 debugs(54, DBG_CRITICAL
, "--> read returned " << x
);
641 debugs(54, DBG_CRITICAL
, "--> got '" << rfc1738_escape(buf1
) << "'");
642 ipcSend(cwfd
, err_string
, strlen(err_string
));
646 x
= write(c2p
[1], (const char *) &PS_ipc
, sizeof(PS_ipc
));
648 if (x
< (ssize_t
)sizeof(PS_ipc
)) {
649 debugs(54, DBG_CRITICAL
, "ipcCreate: CHILD: write FD " << c2p
[1] << ": " << xstrerror());
650 debugs(54, DBG_CRITICAL
, "ipcCreate: CHILD: " << prog
<< ": socket exchange failed");
652 ipcSend(cwfd
, err_string
, strlen(err_string
));
656 x
= read(p2c
[0], buf1
, 8192);
659 debugs(54, DBG_CRITICAL
, "ipcCreate: CHILD: read FD " << p2c
[0] << ": " << xstrerror());
660 debugs(54, DBG_CRITICAL
, "ipcCreate: CHILD: " << prog
<< ": socket exchange failed");
662 ipcSend(cwfd
, err_string
, strlen(err_string
));
664 } else if (strncmp(buf1
, ok_string
, strlen(ok_string
))) {
665 debugs(54, DBG_CRITICAL
, "ipcCreate: CHILD: " << prog
<< ": socket exchange failed");
666 debugs(54, DBG_CRITICAL
, "--> read returned " << x
);
668 debugs(54, DBG_CRITICAL
, "--> got '" << rfc1738_escape(buf1
) << "'");
669 ipcSend(cwfd
, err_string
, strlen(err_string
));
673 x
= send(pwfd_ipc
, (const void *)ok_string
, strlen(ok_string
), 0);
674 x
= recv(prfd_ipc
, (void *)(buf1
+ 200), 8191 - 200, 0);
675 assert((size_t) x
== strlen(ok_string
)
676 && !strncmp(ok_string
, buf1
+ 200, strlen(ok_string
)));
677 } /* IPC_UDP_SOCKET */
679 snprintf(buf1
, 8191, "%s(%ld) CHILD socket", prog
, (long int) pid
);
683 if (prfd_ipc
!= -1) {
684 snprintf(buf1
, 8191, "%s(%ld) <-> ipc CHILD socket", prog
, (long int) pid
);
685 fd_note(crfd_ipc
, buf1
);
686 snprintf(buf1
, 8191, "%s(%ld) <-> ipc PARENT socket", prog
, (long int) pid
);
687 fd_note(prfd_ipc
, buf1
);
690 /* else { IPC_TCP_SOCKET */
691 /* commSetNoLinger(fd); */
693 thread_params
.prog
= prog
;
695 thread_params
.send_fd
= cwfd
;
697 thread_params
.pid
= pid
;
699 if ((thread_params
.type
= type
) == IPC_TCP_SOCKET
)
700 thread_params
.rfd
= p2c
[0];
702 thread_params
.rfd
= prfd_ipc
;
704 thread
= (HANDLE
)_beginthreadex(NULL
, 0, ipc_thread_2
, &thread_params
, 0, NULL
);
707 debugs(54, DBG_CRITICAL
, "ipcCreate: CHILD: _beginthreadex: " << xstrerror());
708 ipcSend(cwfd
, err_string
, strlen(err_string
));
712 snprintf(buf1
, 8191, "%ld\n", (long int) pid
);
714 if (-1 == ipcSend(cwfd
, buf1
, strlen(buf1
)))
717 debugs(54, 2, "ipc(" << prog
<< "," << pid
<< "): started successfully");
721 x
= recv(crfd
, (void *)buf1
, 8192, 0);
724 debugs(54, 3, "ipc(" << prog
<< "," << pid
<< "): " << x
<< " bytes received from parent. Exiting...");
730 if (type
== IPC_UDP_SOCKET
&& !strcmp(buf1
, shutdown_string
)) {
731 debugs(54, 3, "ipc(" << prog
<< "," << pid
<< "): request for shutdown received from parent. Exiting...");
733 TerminateProcess(hProcess
, 0);
737 debugs(54, 5, "ipc(" << prog
<< "," << pid
<< "): received from parent: " << rfc1738_escape_unescaped(buf1
));
739 if (type
== IPC_TCP_SOCKET
)
740 x
= write(c2p
[1], buf1
, x
);
742 x
= send(pwfd_ipc
, (const void *)buf1
, x
, 0);
745 debugs(54, 3, "ipc(" << prog
<< "," << pid
<< "): " << x
<< " bytes written to " << prog
<< ". Exiting...");
758 if (fd_table
[crfd
].flags
.open
)
759 ipcCloseAllFD(-1, -1, crfd
, cwfd
);
761 if (prfd_ipc
!= -1) {
762 send(crfd_ipc
, (const void *)shutdown_string
, strlen(shutdown_string
), 0);
763 shutdown(crfd_ipc
, SD_BOTH
);
764 shutdown(prfd_ipc
, SD_BOTH
);
767 ipcCloseAllFD(prfd_ipc
, pwfd_ipc
, crfd_ipc
, cwfd_ipc
);
769 if (hProcess
&& WAIT_OBJECT_0
!=
770 WaitForSingleObject(hProcess
, type
== IPC_UDP_SOCKET
? 12000 : 5000)) {
773 debugs(54, DBG_CRITICAL
, "ipc(" << prog
<< "," << pid
<< "): WARNING: " << prog
<<
774 " didn't exit in " << (type
== IPC_UDP_SOCKET
? 12 : 5) << " seconds.");
778 if (thread
&& WAIT_OBJECT_0
!= WaitForSingleObject(thread
, 3000)) {
780 debugs(54, DBG_CRITICAL
, "ipc(" << prog
<< "," << pid
<< "): WARNING: ipc_thread_2 didn't exit in 3 seconds.");
787 debugs(54, 2, "ipc(" << prog
<< "," << pid
<< "): normal exit");
799 CloseHandle(hProcess
);
807 static unsigned int __stdcall
808 ipc_thread_2(void *in_params
)
812 struct thread_params
*params
= (struct thread_params
*) in_params
;
813 int type
= params
->type
;
814 int rfd
= params
->rfd
;
815 int send_fd
= params
->send_fd
;
816 char *prog
= xstrdup(params
->prog
);
817 pid_t pid
= params
->pid
;
818 char *buf2
= (char *)xcalloc(1, 8192);
821 if (type
== IPC_TCP_SOCKET
)
822 x
= read(rfd
, buf2
, 8192);
824 x
= recv(rfd
, (void *)buf2
, 8192, 0);
826 if ((x
<= 0 && type
== IPC_TCP_SOCKET
) ||
827 (x
< 0 && type
== IPC_UDP_SOCKET
)) {
828 debugs(54, 3, "ipc(" << prog
<< "," << pid
<< "): " << x
<< " bytes read from " << prog
<< ". Exiting...");
835 if (type
== IPC_UDP_SOCKET
&& !strcmp(buf2
, shutdown_string
)) {
836 debugs(54, 3, "ipc(" << prog
<< "," << pid
<< "): request for shutdown received. Exiting...");
842 if ((buf2
[x
- 1] == '\n') && (buf2
[x
- 2] == '\r')) {
849 debugs(54, 5, "ipc(" << prog
<< "," << pid
<< "): received from child : " << rfc1738_escape_unescaped(buf2
));
851 x
= send(send_fd
, (const void *)buf2
, x
, 0);
853 if ((x
<= 0 && type
== IPC_TCP_SOCKET
) ||
854 (x
< 0 && type
== IPC_UDP_SOCKET
)) {
855 debugs(54, 3, "ipc(" << prog
<< "," << pid
<< "): " << x
<< " bytes sent to parent. Exiting...");