Go to the documentation of this file.
53 static unsigned int __stdcall
ipc_thread_1(
void *params);
54 static unsigned int __stdcall
ipc_thread_2(
void *params);
61 #define HELLO_BUF_SZ 32
97 ipcCreate(
int type,
const char *prog,
const char *
const args[],
const char *name,
Ip::Address &local_addr,
int *rfd,
int *wfd,
void **
hIpc)
103 int optlen =
sizeof(opt);
108 struct addrinfo *aiCS =
nullptr;
109 struct addrinfo *aiPS =
nullptr;
128 if (WIN32_OS_version != _WIN_OS_WINNT) {
129 getsockopt(INVALID_SOCKET, SOL_SOCKET, SO_OPENTYPE, (
char *) &opt, &optlen);
130 opt = opt & ~(SO_SYNCHRONOUS_NONALERT | SO_SYNCHRONOUS_ALERT);
131 setsockopt(INVALID_SOCKET, SOL_SOCKET, SO_OPENTYPE, (
char *) &opt,
sizeof(opt));
157 debugs(54,
DBG_CRITICAL,
"ipcCreate: " << prog <<
": use IPC_TCP_SOCKET instead of IP_FIFO on Windows");
163 debugs(54, 3,
"ipcCreate: prfd FD " << prfd);
164 debugs(54, 3,
"ipcCreate: pwfd FD " << pwfd);
165 debugs(54, 3,
"ipcCreate: crfd FD " << crfd);
166 debugs(54, 3,
"ipcCreate: cwfd FD " << cwfd);
168 if (WIN32_OS_version != _WIN_OS_WINNT) {
169 getsockopt(INVALID_SOCKET, SOL_SOCKET, SO_OPENTYPE, (
char *) &opt, &optlen);
170 opt = opt | SO_SYNCHRONOUS_NONALERT;
171 setsockopt(INVALID_SOCKET, SOL_SOCKET, SO_OPENTYPE, (
char *) &opt, optlen);
189 if (
xgetsockname(pwfd, aiPS->ai_addr, &(aiPS->ai_addrlen) ) < 0) {
199 debugs(54, 3,
"ipcCreate: FD " << pwfd <<
" sockaddr " << tmp_addr );
203 if (
xgetsockname(crfd, aiCS->ai_addr, &(aiCS->ai_addrlen) ) < 0) {
214 debugs(54, 3,
"ipcCreate: FD " << crfd <<
" sockaddr " << tmp_addr );
224 debugs(54, 3,
"ipcCreate: FD " << crfd <<
" listening...");
242 params.
args = (
char **) args;
244 thread = _beginthreadex(
nullptr, 0,
ipc_thread_1, ¶ms, 0,
nullptr);
254 CloseHandle((HANDLE) thread);
265 CloseHandle((HANDLE) thread);
271 CloseHandle((HANDLE) thread);
281 CloseHandle((HANDLE) thread);
292 CloseHandle((HANDLE) thread);
298 CloseHandle((HANDLE) thread);
324 if (GetExitCodeThread((HANDLE) thread, &ecode) && ecode == STILL_ACTIVE) {
326 *
hIpc = (HANDLE) thread;
330 CloseHandle((HANDLE) thread);
338 const auto x =
xsend(cwfd, buf, len, 0);
349 static unsigned int __stdcall
352 int t1, t2, t3, retval = -1;
353 int p2c[2] = {-1, -1};
354 int c2p[2] = {-1, -1};
355 HANDLE hProcess =
nullptr, thread =
nullptr;
363 PROCESS_INFORMATION pi;
365 int prfd_ipc = -1, pwfd_ipc = -1, crfd_ipc = -1, cwfd_ipc = -1;
366 char *
prog =
nullptr, *buf1 =
nullptr;
370 struct addrinfo *aiPS_ipc =
nullptr;
371 struct addrinfo *aiCS_ipc =
nullptr;
382 const size_t bufSz = 8192;
383 buf1 = (
char *)
xcalloc(1, bufSz);
384 strcpy(buf1, params->
prog);
387 if ((str = strrchr(
prog,
'/')))
390 if ((str = strrchr(
prog,
'\\')))
396 debugs(54, 3,
"ipcCreate: calling accept on FD " <<
crfd);
404 debugs(54, 3,
"ipcCreate: CHILD accepted new FD " << fd);
406 snprintf(buf1, bufSz-1,
"%s CHILD socket",
prog);
425 memset(buf1,
'\0', bufSz);
426 x =
xrecv(
crfd, (
void *)buf1, bufSz-1, 0);
441 if (_pipe(p2c, 1024, _O_BINARY | _O_NOINHERIT) < 0) {
448 if (_pipe(c2p, 1024, _O_BINARY | _O_NOINHERIT) < 0) {
456 snprintf(buf1, bufSz,
"%s(%ld) <-> ipc CHILD socket",
prog, -1L);
465 snprintf(buf1, bufSz,
"%s(%ld) <-> ipc PARENT socket",
prog, -1L);
476 if (
xgetsockname(pwfd_ipc, aiPS_ipc->ai_addr, &(aiPS_ipc->ai_addrlen)) < 0) {
487 debugs(54, 3,
"ipcCreate: FD " << pwfd_ipc <<
" sockaddr " << PS_ipc);
491 if (
xgetsockname(crfd_ipc, aiCS_ipc->ai_addr, &(aiCS_ipc->ai_addrlen)) < 0) {
502 debugs(54, 3,
"ipcCreate: FD " << crfd_ipc <<
" sockaddr " << CS_ipc);
535 memset(&si, 0,
sizeof(STARTUPINFO));
537 si.cb =
sizeof(STARTUPINFO);
539 si.hStdInput = (HANDLE) _get_osfhandle(0);
541 si.hStdOutput = (HANDLE) _get_osfhandle(1);
543 si.hStdError = (HANDLE) _get_osfhandle(2);
545 si.dwFlags = STARTF_USESTDHANDLES;
549 if ((
F = _get_osfhandle(x)) == -1)
552 SetHandleInformation((HANDLE)
F, HANDLE_FLAG_INHERIT, 0);
556 strcpy(buf1 + 4096, params->
prog);
557 str = strtok(buf1 + 4096,
w_space);
562 }
while ((str = strtok(
nullptr,
w_space)));
567 strcat(buf1,
args[x]);
572 if (CreateProcess(buf1 + 4096, buf1,
nullptr,
nullptr,
TRUE, CREATE_NO_WINDOW,
573 nullptr,
nullptr, &si, &pi)) {
574 pid = pi.dwProcessId;
575 hProcess = pi.hProcess;
596 WSAPROTOCOL_INFO wpi;
598 memset(&wpi, 0,
sizeof(wpi));
600 if (SOCKET_ERROR == WSADuplicateSocket(crfd_ipc,
pid, &wpi)) {
607 x =
xwrite(c2p[1], (
const char *) &wpi,
sizeof(wpi));
609 if (x < (ssize_t)
sizeof(wpi)) {
617 x =
xread(p2c[0], buf1, bufSz-1);
634 x =
xwrite(c2p[1], (
const char *) &PS_ipc,
sizeof(PS_ipc));
636 if (x < (ssize_t)
sizeof(PS_ipc)) {
644 x =
xread(p2c[0], buf1, bufSz-1);
662 x =
xrecv(prfd_ipc, (
void *)(buf1 + 200), bufSz -1 - 200, 0);
667 snprintf(buf1, bufSz-1,
"%s(%ld) CHILD socket",
prog, (
long int)
pid);
671 if (prfd_ipc != -1) {
672 snprintf(buf1, bufSz-1,
"%s(%ld) <-> ipc CHILD socket",
prog, (
long int)
pid);
674 snprintf(buf1, bufSz-1,
"%s(%ld) <-> ipc PARENT socket",
prog, (
long int)
pid);
701 snprintf(buf1, bufSz-1,
"%ld\n", (
long int)
pid);
706 debugs(54, 2,
"ipc(" <<
prog <<
"," <<
pid <<
"): started successfully");
710 x =
xrecv(
crfd, (
void *)buf1, bufSz-1, 0);
713 debugs(54, 3,
"ipc(" <<
prog <<
"," <<
pid <<
"): " << x <<
" bytes received from parent. Exiting...");
720 debugs(54, 3,
"ipc(" <<
prog <<
"," <<
pid <<
"): request for shutdown received from parent. Exiting...");
722 TerminateProcess(hProcess, 0);
729 x =
xwrite(c2p[1], buf1, x);
731 x =
xsend(pwfd_ipc, buf1, x, 0);
734 debugs(54, 3,
"ipc(" <<
prog <<
"," <<
pid <<
"): " << x <<
" bytes written to " <<
prog <<
". Exiting...");
750 if (prfd_ipc != -1) {
752 shutdown(crfd_ipc, SD_BOTH);
753 shutdown(prfd_ipc, SD_BOTH);
758 if (hProcess && WAIT_OBJECT_0 !=
767 if (thread && WAIT_OBJECT_0 != WaitForSingleObject(thread, 3000)) {
776 debugs(54, 2,
"ipc(" <<
prog <<
"," <<
pid <<
"): normal exit");
785 CloseHandle(hProcess);
793 static unsigned int __stdcall
804 const size_t bufSz = 8192;
805 char *buf2 = (
char *)
xcalloc(1, bufSz);
811 x =
xrecv(
rfd, (
void *)buf2, bufSz-1, 0);
815 debugs(54, 3,
"ipc(" <<
prog <<
"," <<
pid <<
"): " << x <<
" bytes read from " <<
prog <<
". Exiting...");
823 debugs(54, 3,
"ipc(" <<
prog <<
"," <<
pid <<
"): request for shutdown received. Exiting...");
828 if ((buf2[x - 1] ==
'\n') && (buf2[x - 2] ==
'\r')) {
841 debugs(54, 3,
"ipc(" <<
prog <<
"," <<
pid <<
"): " << x <<
" bytes sent to parent. Exiting...");
static char * debugOptions
const char * xstrerr(int error)
static void PutEnvironment()
void * xcalloc(size_t n, size_t sz)
int xaccept(int socketFd, struct sockaddr *sa, socklen_t *saLength)
POSIX accept(2) equivalent.
void fd_note(int fd, const char *s)
void commSetCloseOnExec(int)
static const char * ok_string
static unsigned int __stdcall ipc_thread_2(void *params)
int comm_connect_addr(int sock, const Ip::Address &address)
static uint32 F(uint32 X, uint32 Y, uint32 Z)
int xwrite(int fd, const void *buf, size_t bufSize)
POSIX write(2) equivalent.
int commSetNonBlocking(int fd)
static void FreeAddr(struct addrinfo *&ai)
#define rfc1738_escape(x)
static unsigned int __stdcall ipc_thread_1(void *params)
void fd_open(const int fd, unsigned int, const char *description)
static const char * shutdown_string
void requirePathnameExists(const char *name, const char *path)
ssize_t xsend(int socketFd, const void *buf, size_t bufLength, int flags)
POSIX send(2) equivalent.
void comm_open_listener(int sock_type, int proto, Comm::ConnectionPointer &conn, const char *note)
int commUnsetNonBlocking(int fd)
int xgetsockname(int socketFd, struct sockaddr *sa, socklen_t *saLength)
POSIX getsockname(2) equivalent.
void commUnsetFdTimeout(int fd)
clear a timeout handler by FD number
time_t getCurrentTime() STUB_RETVAL(0) int tvSubUsec(struct timeval
static int ipcSend(int cwfd, const char *buf, int len)
static const char * err_string
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)
int comm_open(int sock_type, int proto, Ip::Address &addr, int flags, const char *note)
static int ipcCloseAllFD(int prfd, int pwfd, int crfd, int cwfd)
static const char * hello_string
void setEmpty()
Fast reset of the stored content to what would be after default constructor.
#define rfc1738_escape_unescaped(x)
ssize_t xrecv(int socketFd, void *buf, size_t bufLength, int flags)
POSIX recv(2) equivalent.
int xread(int fd, void *buf, size_t bufSize)
POSIX read(2) equivalent.
#define debugs(SECTION, LEVEL, CONTENT)
static void InitAddr(struct addrinfo *&ai)
int xlisten(int socketFd, int backlog)
POSIX listen(2) equivalent.
static char hello_buf[HELLO_BUF_SZ]