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
91 ipcCreate(
int type,
const char *prog,
const char *
const args[],
const char *name,
Ip::Address &local_addr,
int *rfd,
int *wfd,
void **
hIpc)
97 int optlen =
sizeof(opt);
102 struct addrinfo *aiCS =
nullptr;
103 struct addrinfo *aiPS =
nullptr;
122 if (WIN32_OS_version != _WIN_OS_WINNT) {
123 getsockopt(INVALID_SOCKET, SOL_SOCKET, SO_OPENTYPE, (
char *) &opt, &optlen);
124 opt = opt & ~(SO_SYNCHRONOUS_NONALERT | SO_SYNCHRONOUS_ALERT);
125 setsockopt(INVALID_SOCKET, SOL_SOCKET, SO_OPENTYPE, (
char *) &opt,
sizeof(opt));
151 debugs(54,
DBG_CRITICAL,
"ipcCreate: " << prog <<
": use IPC_TCP_SOCKET instead of IP_FIFO on Windows");
157 debugs(54, 3,
"ipcCreate: prfd FD " << prfd);
158 debugs(54, 3,
"ipcCreate: pwfd FD " << pwfd);
159 debugs(54, 3,
"ipcCreate: crfd FD " << crfd);
160 debugs(54, 3,
"ipcCreate: cwfd FD " << cwfd);
162 if (WIN32_OS_version != _WIN_OS_WINNT) {
163 getsockopt(INVALID_SOCKET, SOL_SOCKET, SO_OPENTYPE, (
char *) &opt, &optlen);
164 opt = opt | SO_SYNCHRONOUS_NONALERT;
165 setsockopt(INVALID_SOCKET, SOL_SOCKET, SO_OPENTYPE, (
char *) &opt, optlen);
183 if (
xgetsockname(pwfd, aiPS->ai_addr, &(aiPS->ai_addrlen) ) < 0) {
193 debugs(54, 3,
"ipcCreate: FD " << pwfd <<
" sockaddr " << tmp_addr );
197 if (
xgetsockname(crfd, aiCS->ai_addr, &(aiCS->ai_addrlen) ) < 0) {
208 debugs(54, 3,
"ipcCreate: FD " << crfd <<
" sockaddr " << tmp_addr );
218 debugs(54, 3,
"ipcCreate: FD " << crfd <<
" listening...");
236 params.
args = (
char **) args;
238 thread = _beginthreadex(
nullptr, 0,
ipc_thread_1, ¶ms, 0,
nullptr);
248 CloseHandle((HANDLE) thread);
259 CloseHandle((HANDLE) thread);
265 CloseHandle((HANDLE) thread);
275 CloseHandle((HANDLE) thread);
286 CloseHandle((HANDLE) thread);
292 CloseHandle((HANDLE) thread);
318 if (GetExitCodeThread((HANDLE) thread, &ecode) && ecode == STILL_ACTIVE) {
320 *
hIpc = (HANDLE) thread;
324 CloseHandle((HANDLE) thread);
332 const auto x =
xsend(cwfd, buf, len, 0);
343 static unsigned int __stdcall
346 int t1, t2, t3, retval = -1;
347 int p2c[2] = {-1, -1};
348 int c2p[2] = {-1, -1};
349 HANDLE hProcess =
nullptr, thread =
nullptr;
357 PROCESS_INFORMATION pi;
359 int prfd_ipc = -1, pwfd_ipc = -1, crfd_ipc = -1, cwfd_ipc = -1;
360 char *
prog =
nullptr, *buf1 =
nullptr;
364 struct addrinfo *aiPS_ipc =
nullptr;
365 struct addrinfo *aiCS_ipc =
nullptr;
376 const size_t bufSz = 8192;
377 buf1 = (
char *)
xcalloc(1, bufSz);
378 strcpy(buf1, params->
prog);
381 if ((str = strrchr(
prog,
'/')))
384 if ((str = strrchr(
prog,
'\\')))
390 debugs(54, 3,
"ipcCreate: calling accept on FD " <<
crfd);
398 debugs(54, 3,
"ipcCreate: CHILD accepted new FD " << fd);
400 snprintf(buf1, bufSz-1,
"%s CHILD socket",
prog);
419 memset(buf1,
'\0', bufSz);
420 x =
xrecv(
crfd, (
void *)buf1, bufSz-1, 0);
435 if (_pipe(p2c, 1024, _O_BINARY | _O_NOINHERIT) < 0) {
442 if (_pipe(c2p, 1024, _O_BINARY | _O_NOINHERIT) < 0) {
450 snprintf(buf1, bufSz,
"%s(%ld) <-> ipc CHILD socket",
prog, -1L);
459 snprintf(buf1, bufSz,
"%s(%ld) <-> ipc PARENT socket",
prog, -1L);
470 if (
xgetsockname(pwfd_ipc, aiPS_ipc->ai_addr, &(aiPS_ipc->ai_addrlen)) < 0) {
481 debugs(54, 3,
"ipcCreate: FD " << pwfd_ipc <<
" sockaddr " << PS_ipc);
485 if (
xgetsockname(crfd_ipc, aiCS_ipc->ai_addr, &(aiCS_ipc->ai_addrlen)) < 0) {
496 debugs(54, 3,
"ipcCreate: FD " << crfd_ipc <<
" sockaddr " << CS_ipc);
529 memset(&si, 0,
sizeof(STARTUPINFO));
531 si.cb =
sizeof(STARTUPINFO);
533 si.hStdInput = (HANDLE) _get_osfhandle(0);
535 si.hStdOutput = (HANDLE) _get_osfhandle(1);
537 si.hStdError = (HANDLE) _get_osfhandle(2);
539 si.dwFlags = STARTF_USESTDHANDLES;
543 if ((F = _get_osfhandle(x)) == -1)
546 SetHandleInformation((HANDLE) F, HANDLE_FLAG_INHERIT, 0);
550 strcpy(buf1 + 4096, params->
prog);
551 str = strtok(buf1 + 4096,
w_space);
556 }
while ((str = strtok(
nullptr,
w_space)));
561 strcat(buf1,
args[x]);
566 if (CreateProcess(buf1 + 4096, buf1,
nullptr,
nullptr,
TRUE, CREATE_NO_WINDOW,
567 nullptr,
nullptr, &si, &pi)) {
568 pid = pi.dwProcessId;
569 hProcess = pi.hProcess;
570 CloseHandle(pi.hThread);
591 WSAPROTOCOL_INFO wpi;
593 memset(&wpi, 0,
sizeof(wpi));
595 if (SOCKET_ERROR == WSADuplicateSocket(crfd_ipc,
pid, &wpi)) {
602 x =
xwrite(c2p[1], (
const char *) &wpi,
sizeof(wpi));
604 if (x < (ssize_t)
sizeof(wpi)) {
612 x =
xread(p2c[0], buf1, bufSz-1);
629 x =
xwrite(c2p[1], (
const char *) &PS_ipc,
sizeof(PS_ipc));
631 if (x < (ssize_t)
sizeof(PS_ipc)) {
639 x =
xread(p2c[0], buf1, bufSz-1);
657 x =
xrecv(prfd_ipc, (
void *)(buf1 + 200), bufSz -1 - 200, 0);
662 snprintf(buf1, bufSz-1,
"%s(%ld) CHILD socket",
prog, (
long int)
pid);
666 if (prfd_ipc != -1) {
667 snprintf(buf1, bufSz-1,
"%s(%ld) <-> ipc CHILD socket",
prog, (
long int)
pid);
669 snprintf(buf1, bufSz-1,
"%s(%ld) <-> ipc PARENT socket",
prog, (
long int)
pid);
696 snprintf(buf1, bufSz-1,
"%ld\n", (
long int)
pid);
701 debugs(54, 2,
"ipc(" <<
prog <<
"," <<
pid <<
"): started successfully");
705 x =
xrecv(
crfd, (
void *)buf1, bufSz-1, 0);
708 debugs(54, 3,
"ipc(" <<
prog <<
"," <<
pid <<
"): " << x <<
" bytes received from parent. Exiting...");
715 debugs(54, 3,
"ipc(" <<
prog <<
"," <<
pid <<
"): request for shutdown received from parent. Exiting...");
717 TerminateProcess(hProcess, 0);
724 x =
xwrite(c2p[1], buf1, x);
726 x =
xsend(pwfd_ipc, buf1, x, 0);
729 debugs(54, 3,
"ipc(" <<
prog <<
"," <<
pid <<
"): " << x <<
" bytes written to " <<
prog <<
". Exiting...");
745 if (prfd_ipc != -1) {
747 shutdown(crfd_ipc, SD_BOTH);
748 shutdown(prfd_ipc, SD_BOTH);
753 if (hProcess && WAIT_OBJECT_0 !=
762 if (thread && WAIT_OBJECT_0 != WaitForSingleObject(thread, 3000)) {
771 debugs(54, 2,
"ipc(" <<
prog <<
"," <<
pid <<
"): normal exit");
780 CloseHandle(hProcess);
788 static unsigned int __stdcall
799 const size_t bufSz = 8192;
800 char *buf2 = (
char *)
xcalloc(1, bufSz);
806 x =
xrecv(
rfd, (
void *)buf2, bufSz-1, 0);
810 debugs(54, 3,
"ipc(" <<
prog <<
"," <<
pid <<
"): " << x <<
" bytes read from " <<
prog <<
". Exiting...");
818 debugs(54, 3,
"ipc(" <<
prog <<
"," <<
pid <<
"): request for shutdown received. Exiting...");
823 if ((buf2[x - 1] ==
'\n') && (buf2[x - 2] ==
'\r')) {
836 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)
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]