56#define HELLO_BUF_SZ 32
92ipcCreate(
int type,
const char *prog,
const char *
const args[],
const char *name,
Ip::Address &local_addr,
int *rfd,
int *wfd,
void **
hIpc)
98 int optlen =
sizeof(opt);
123 if (WIN32_OS_version != _WIN_OS_WINNT) {
124 getsockopt(INVALID_SOCKET, SOL_SOCKET, SO_OPENTYPE, (
char *) &opt, &optlen);
125 opt = opt & ~(SO_SYNCHRONOUS_NONALERT | SO_SYNCHRONOUS_ALERT);
126 setsockopt(INVALID_SOCKET, SOL_SOCKET, SO_OPENTYPE, (
char *) &opt,
sizeof(opt));
152 debugs(54,
DBG_CRITICAL,
"ipcCreate: " << prog <<
": use IPC_TCP_SOCKET instead of IP_FIFO on Windows");
158 debugs(54, 3,
"ipcCreate: prfd FD " << prfd);
159 debugs(54, 3,
"ipcCreate: pwfd FD " << pwfd);
160 debugs(54, 3,
"ipcCreate: crfd FD " << crfd);
161 debugs(54, 3,
"ipcCreate: cwfd FD " << cwfd);
163 if (WIN32_OS_version != _WIN_OS_WINNT) {
164 getsockopt(INVALID_SOCKET, SOL_SOCKET, SO_OPENTYPE, (
char *) &opt, &optlen);
165 opt = opt | SO_SYNCHRONOUS_NONALERT;
166 setsockopt(INVALID_SOCKET, SOL_SOCKET, SO_OPENTYPE, (
char *) &opt, optlen);
194 debugs(54, 3,
"ipcCreate: FD " << pwfd <<
" sockaddr " << tmp_addr );
209 debugs(54, 3,
"ipcCreate: FD " << crfd <<
" sockaddr " << tmp_addr );
213 if (listen(crfd, 1) < 0) {
219 debugs(54, 3,
"ipcCreate: FD " << crfd <<
" listening...");
237 params.
args = (
char **) args;
249 CloseHandle((HANDLE) thread);
260 CloseHandle((HANDLE) thread);
266 CloseHandle((HANDLE) thread);
276 CloseHandle((HANDLE) thread);
287 CloseHandle((HANDLE) thread);
293 CloseHandle((HANDLE) thread);
327 if (GetExitCodeThread((HANDLE) thread, &ecode) && ecode == STILL_ACTIVE) {
329 *
hIpc = (HANDLE) thread;
333 CloseHandle((HANDLE) thread);
341 int x = send(cwfd, (
const void *)buf, len, 0);
352static unsigned int __stdcall
355 int t1, t2, t3, retval = -1;
356 int p2c[2] = {-1, -1};
357 int c2p[2] = {-1, -1};
358 HANDLE hProcess =
NULL, thread =
NULL;
366 PROCESS_INFORMATION pi;
368 int prfd_ipc = -1, pwfd_ipc = -1, crfd_ipc = -1, cwfd_ipc = -1;
385 const size_t bufSz = 8192;
386 buf1 = (
char *)
xcalloc(1, bufSz);
387 strcpy(buf1, params->
prog);
390 if ((str = strrchr(
prog,
'/')))
393 if ((str = strrchr(
prog,
'\\')))
399 debugs(54, 3,
"ipcCreate: calling accept on FD " <<
crfd);
407 debugs(54, 3,
"ipcCreate: CHILD accepted new FD " << fd);
409 snprintf(buf1, bufSz-1,
"%s CHILD socket",
prog);
428 memset(buf1,
'\0', bufSz);
429 x = recv(
crfd, (
void *)buf1, bufSz-1, 0);
444 if (_pipe(p2c, 1024, _O_BINARY | _O_NOINHERIT) < 0) {
451 if (_pipe(c2p, 1024, _O_BINARY | _O_NOINHERIT) < 0) {
459 snprintf(buf1, bufSz,
"%s(%ld) <-> ipc CHILD socket",
prog, -1L);
468 snprintf(buf1, bufSz,
"%s(%ld) <-> ipc PARENT socket",
prog, -1L);
490 debugs(54, 3,
"ipcCreate: FD " << pwfd_ipc <<
" sockaddr " << PS_ipc);
505 debugs(54, 3,
"ipcCreate: FD " << crfd_ipc <<
" sockaddr " << CS_ipc);
538 memset(&si, 0,
sizeof(STARTUPINFO));
540 si.cb =
sizeof(STARTUPINFO);
542 si.hStdInput = (HANDLE) _get_osfhandle(0);
544 si.hStdOutput = (HANDLE) _get_osfhandle(1);
546 si.hStdError = (HANDLE) _get_osfhandle(2);
548 si.dwFlags = STARTF_USESTDHANDLES;
552 if ((
F = _get_osfhandle(x)) == -1)
555 SetHandleInformation((HANDLE)
F, HANDLE_FLAG_INHERIT, 0);
559 strcpy(buf1 + 4096, params->
prog);
560 str = strtok(buf1 + 4096,
w_space);
570 strcat(buf1,
args[x]);
575 if (CreateProcess(buf1 + 4096, buf1,
NULL,
NULL,
TRUE, CREATE_NO_WINDOW,
577 pid = pi.dwProcessId;
578 hProcess = pi.hProcess;
599 WSAPROTOCOL_INFO wpi;
601 memset(&wpi, 0,
sizeof(wpi));
603 if (SOCKET_ERROR == WSADuplicateSocket(crfd_ipc,
pid, &wpi)) {
610 x = write(c2p[1], (
const char *) &wpi,
sizeof(wpi));
612 if (x < (ssize_t)
sizeof(wpi)) {
620 x = read(p2c[0], buf1, bufSz-1);
637 x = write(c2p[1], (
const char *) &PS_ipc,
sizeof(PS_ipc));
639 if (x < (ssize_t)
sizeof(PS_ipc)) {
647 x = read(p2c[0], buf1, bufSz-1);
665 x = recv(prfd_ipc, (
void *)(buf1 + 200), bufSz -1 - 200, 0);
670 snprintf(buf1, bufSz-1,
"%s(%ld) CHILD socket",
prog, (
long int)
pid);
674 if (prfd_ipc != -1) {
675 snprintf(buf1, bufSz-1,
"%s(%ld) <-> ipc CHILD socket",
prog, (
long int)
pid);
677 snprintf(buf1, bufSz-1,
"%s(%ld) <-> ipc PARENT socket",
prog, (
long int)
pid);
704 snprintf(buf1, bufSz-1,
"%ld\n", (
long int)
pid);
709 debugs(54, 2,
"ipc(" <<
prog <<
"," <<
pid <<
"): started successfully");
713 x = recv(
crfd, (
void *)buf1, bufSz-1, 0);
716 debugs(54, 3,
"ipc(" <<
prog <<
"," <<
pid <<
"): " << x <<
" bytes received from parent. Exiting...");
723 debugs(54, 3,
"ipc(" <<
prog <<
"," <<
pid <<
"): request for shutdown received from parent. Exiting...");
725 TerminateProcess(hProcess, 0);
732 x = write(c2p[1], buf1, x);
734 x = send(pwfd_ipc, (
const void *)buf1, x, 0);
737 debugs(54, 3,
"ipc(" <<
prog <<
"," <<
pid <<
"): " << x <<
" bytes written to " <<
prog <<
". Exiting...");
753 if (prfd_ipc != -1) {
755 shutdown(crfd_ipc, SD_BOTH);
756 shutdown(prfd_ipc, SD_BOTH);
761 if (hProcess && WAIT_OBJECT_0 !=
770 if (thread && WAIT_OBJECT_0 != WaitForSingleObject(thread, 3000)) {
779 debugs(54, 2,
"ipc(" <<
prog <<
"," <<
pid <<
"): normal exit");
788 CloseHandle(hProcess);
796static unsigned int __stdcall
807 const size_t bufSz = 8192;
808 char *buf2 = (
char *)
xcalloc(1, bufSz);
812 x = read(
rfd, buf2, bufSz-1);
814 x = recv(
rfd, (
void *)buf2, bufSz-1, 0);
818 debugs(54, 3,
"ipc(" <<
prog <<
"," <<
pid <<
"): " << x <<
" bytes read from " <<
prog <<
". Exiting...");
826 debugs(54, 3,
"ipc(" <<
prog <<
"," <<
pid <<
"): request for shutdown received. Exiting...");
831 if ((buf2[x - 1] ==
'\n') && (buf2[x - 2] ==
'\r')) {
840 x = send(
send_fd, (
const void *)buf2, x, 0);
844 debugs(54, 3,
"ipc(" <<
prog <<
"," <<
pid <<
"): " << x <<
" bytes sent to parent. Exiting...");
void requirePathnameExists(const char *name, const char *path)
static char * debugOptions
void setEmpty()
Fast reset of the stored content to what would be after default constructor.
static void InitAddr(struct addrinfo *&ai)
static void FreeAddr(struct addrinfo *&ai)
void fd_open(const int fd, unsigned int, const char *description)
int commSetNonBlocking(int fd)
void commSetCloseOnExec(int fd)
void commUnsetFdTimeout(int fd)
clear a timeout handler by FD number
int commUnsetNonBlocking(int fd)
void comm_open_listener(int sock_type, int proto, Comm::ConnectionPointer &conn, const char *note)
int comm_open(int sock_type, int proto, Ip::Address &addr, int flags, const char *note)
int comm_connect_addr(int sock, const Ip::Address &address)
#define debugs(SECTION, LEVEL, CONTENT)
#define debug_log
change-avoidance macro; new code should call DebugStream() instead
void fd_note(int fd, const char *s)
static void PutEnvironment()
static int ipcSend(int cwfd, const char *buf, int len)
static const char * hello_string
static char hello_buf[HELLO_BUF_SZ]
static unsigned int __stdcall ipc_thread_1(void *params)
static const char * ok_string
static int ipcCloseAllFD(int prfd, int pwfd, int crfd, int cwfd)
pid_t ipcCreate(int type, const char *prog, const char *const args[], const char *name, Ip::Address &local_addr, int *rfd, int *wfd, void **hIpc)
static unsigned int __stdcall ipc_thread_2(void *params)
static const char * shutdown_string
static const char * err_string
static uint32 F(uint32 X, uint32 Y, uint32 Z)
#define rfc1738_escape(x)
#define rfc1738_escape_unescaped(x)
struct sockaddr * ai_addr
time_t getCurrentTime() STUB_RETVAL(0) int tvSubUsec(struct timeval
void * xcalloc(size_t n, size_t sz)
const char * xstrerr(int error)