59#define HELLO_BUF_SZ 32
95ipcCreate(
int type,
const char *prog,
const char *
const args[],
const char *name,
Ip::Address &local_addr,
int *rfd,
int *wfd,
void **
hIpc)
101 int optlen =
sizeof(opt);
106 struct addrinfo *aiCS =
nullptr;
107 struct addrinfo *aiPS =
nullptr;
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));
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);
187 if (getsockname(pwfd, aiPS->ai_addr, &(aiPS->ai_addrlen) ) < 0) {
197 debugs(54, 3,
"ipcCreate: FD " << pwfd <<
" sockaddr " << tmp_addr );
201 if (getsockname(crfd, aiCS->ai_addr, &(aiCS->ai_addrlen) ) < 0) {
212 debugs(54, 3,
"ipcCreate: FD " << crfd <<
" sockaddr " << tmp_addr );
216 if (listen(crfd, 1) < 0) {
222 debugs(54, 3,
"ipcCreate: FD " << crfd <<
" listening...");
240 params.
args = (
char **) args;
242 thread = _beginthreadex(
nullptr, 0,
ipc_thread_1, ¶ms, 0,
nullptr);
252 CloseHandle((HANDLE) thread);
263 CloseHandle((HANDLE) thread);
269 CloseHandle((HANDLE) thread);
279 CloseHandle((HANDLE) thread);
290 CloseHandle((HANDLE) thread);
296 CloseHandle((HANDLE) thread);
322 if (GetExitCodeThread((HANDLE) thread, &ecode) && ecode == STILL_ACTIVE) {
324 *
hIpc = (HANDLE) thread;
328 CloseHandle((HANDLE) thread);
336 int x = send(cwfd, (
const void *)buf, len, 0);
347static unsigned int __stdcall
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;
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;
380 const size_t bufSz = 8192;
381 buf1 = (
char *)
xcalloc(1, bufSz);
382 strcpy(buf1, params->
prog);
385 if ((str = strrchr(
prog,
'/')))
388 if ((str = strrchr(
prog,
'\\')))
394 debugs(54, 3,
"ipcCreate: calling accept on FD " <<
crfd);
396 if ((fd = accept(
crfd,
nullptr,
nullptr)) < 0) {
402 debugs(54, 3,
"ipcCreate: CHILD accepted new FD " << fd);
404 snprintf(buf1, bufSz-1,
"%s CHILD socket",
prog);
423 memset(buf1,
'\0', bufSz);
424 x = recv(
crfd, (
void *)buf1, bufSz-1, 0);
439 if (_pipe(p2c, 1024, _O_BINARY | _O_NOINHERIT) < 0) {
446 if (_pipe(c2p, 1024, _O_BINARY | _O_NOINHERIT) < 0) {
454 snprintf(buf1, bufSz,
"%s(%ld) <-> ipc CHILD socket",
prog, -1L);
463 snprintf(buf1, bufSz,
"%s(%ld) <-> ipc PARENT socket",
prog, -1L);
474 if (getsockname(pwfd_ipc, aiPS_ipc->ai_addr, &(aiPS_ipc->ai_addrlen)) < 0) {
485 debugs(54, 3,
"ipcCreate: FD " << pwfd_ipc <<
" sockaddr " << PS_ipc);
489 if (getsockname(crfd_ipc, aiCS_ipc->ai_addr, &(aiCS_ipc->ai_addrlen)) < 0) {
500 debugs(54, 3,
"ipcCreate: FD " << crfd_ipc <<
" sockaddr " << CS_ipc);
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;
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;
594 WSAPROTOCOL_INFO wpi;
596 memset(&wpi, 0,
sizeof(wpi));
598 if (SOCKET_ERROR == WSADuplicateSocket(crfd_ipc,
pid, &wpi)) {
605 x = write(c2p[1], (
const char *) &wpi,
sizeof(wpi));
607 if (x < (ssize_t)
sizeof(wpi)) {
615 x = read(p2c[0], buf1, bufSz-1);
632 x = write(c2p[1], (
const char *) &PS_ipc,
sizeof(PS_ipc));
634 if (x < (ssize_t)
sizeof(PS_ipc)) {
642 x = read(p2c[0], buf1, bufSz-1);
660 x = recv(prfd_ipc, (
void *)(buf1 + 200), bufSz -1 - 200, 0);
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);
672 snprintf(buf1, bufSz-1,
"%s(%ld) <-> ipc PARENT socket",
prog, (
long int)
pid);
699 snprintf(buf1, bufSz-1,
"%ld\n", (
long int)
pid);
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...");
718 debugs(54, 3,
"ipc(" <<
prog <<
"," <<
pid <<
"): request for shutdown received from parent. Exiting...");
720 TerminateProcess(hProcess, 0);
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...");
748 if (prfd_ipc != -1) {
750 shutdown(crfd_ipc, SD_BOTH);
751 shutdown(prfd_ipc, SD_BOTH);
756 if (hProcess && WAIT_OBJECT_0 !=
765 if (thread && WAIT_OBJECT_0 != WaitForSingleObject(thread, 3000)) {
774 debugs(54, 2,
"ipc(" <<
prog <<
"," <<
pid <<
"): normal exit");
783 CloseHandle(hProcess);
791static unsigned int __stdcall
802 const size_t bufSz = 8192;
803 char *buf2 = (
char *)
xcalloc(1, bufSz);
807 x = read(
rfd, buf2, bufSz-1);
809 x = recv(
rfd, (
void *)buf2, bufSz-1, 0);
813 debugs(54, 3,
"ipc(" <<
prog <<
"," <<
pid <<
"): " << x <<
" bytes read from " <<
prog <<
". Exiting...");
821 debugs(54, 3,
"ipc(" <<
prog <<
"," <<
pid <<
"): request for shutdown received. Exiting...");
826 if ((buf2[x - 1] ==
'\n') && (buf2[x - 2] ==
'\r')) {
835 x = send(
send_fd, (
const void *)buf2, x, 0);
839 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)
time_t getCurrentTime() STUB_RETVAL(0) int tvSubUsec(struct timeval
void * xcalloc(size_t n, size_t sz)
const char * xstrerr(int error)