int zmq::ctx_t::terminate () { slot_sync.lock(); bool saveTerminating = terminating; terminating = false; // Connect up any pending inproc connections, otherwise we will hang pending_connections_t copy = pending_connections; for (pending_connections_t::iterator p = copy.begin (); p != copy.end (); ++p) { zmq::socket_base_t *s = create_socket (ZMQ_PAIR); s->bind (p->first.c_str ()); s->close (); } terminating = saveTerminating; if (!starting) { #ifdef HAVE_FORK if (pid != getpid ()) { // we are a forked child process. Close all file descriptors // inherited from the parent. for (sockets_t::size_type i = 0; i != sockets.size (); i++) sockets [i]->get_mailbox ()->forked (); term_mailbox.forked (); } #endif // Check whether termination was already underway, but interrupted and now // restarted. bool restarted = terminating; terminating = true; // First attempt to terminate the context. if (!restarted) { // First send stop command to sockets so that any blocking calls // can be interrupted. If there are no sockets we can ask reaper // thread to stop. for (sockets_t::size_type i = 0; i != sockets.size (); i++) sockets [i]->stop (); if (sockets.empty ()) reaper->stop (); } slot_sync.unlock(); // Wait till reaper thread closes all the sockets. command_t cmd; int rc = term_mailbox.recv (&cmd, -1); if (rc == -1 && errno == EINTR) return -1; errno_assert (rc == 0); zmq_assert (cmd.type == command_t::done); slot_sync.lock (); zmq_assert (sockets.empty ()); } slot_sync.unlock (); #ifdef ZMQ_HAVE_VMCI vmci_sync.lock (); VMCISock_ReleaseAFValueFd (vmci_fd); vmci_family = -1; vmci_fd = -1; vmci_sync.unlock (); #endif // Deallocate the resources. delete this; return 0; }
SOCKET Socket_ConnectVMCI(unsigned int cid, // IN unsigned int port, // IN gboolean isPriv, // IN SockConnError *outError) // OUT { struct sockaddr_vm addr; SOCKET fd; SockConnError error = SOCKERR_GENERIC; int sysErr; socklen_t addrLen = sizeof addr; int vsockDev = -1; int family = VMCISock_GetAFValueFd(&vsockDev); if (outError) { *outError = SOCKERR_SUCCESS; } if (!SocketStartup()) { goto error; } if (family == -1) { Warning(LGPFX "Couldn't get VMCI socket family info."); goto error; } memset((char *)&addr, 0, sizeof addr); addr.svm_family = family; addr.svm_cid = cid; addr.svm_port = port; Debug(LGPFX "creating new socket, connecting to %u:%u\n", cid, port); fd = socket(addr.svm_family, SOCK_STREAM, 0); if (fd == INVALID_SOCKET) { sysErr = SocketGetLastError(); Warning(LGPFX "failed to create socket, error %d: %s\n", sysErr, Err_Errno2String(sysErr)); goto error; } if (isPriv) { struct sockaddr_vm localAddr; gboolean bindOk = FALSE; int localPort; memset(&localAddr, 0, sizeof localAddr); localAddr.svm_family = addr.svm_family; localAddr.svm_cid = VMCISock_GetLocalCID(); /* Try to bind to port 1~1023 for a privileged user. */ for (localPort = PRIVILEGED_PORT_MAX; localPort >= PRIVILEGED_PORT_MIN; localPort--) { localAddr.svm_port = localPort; if (bind(fd, (struct sockaddr *)&localAddr, sizeof localAddr) != 0) { sysErr = SocketGetLastError(); if (sysErr == SYSERR_EACCESS) { Warning(LGPFX "Couldn't bind to privileged port for " "socket %d\n", fd); error = SOCKERR_EACCESS; Socket_Close(fd); goto error; } if (sysErr == SYSERR_EADDRINUSE) { continue; } Warning(LGPFX "could not bind socket, error %d: %s\n", sysErr, Err_Errno2String(sysErr)); Socket_Close(fd); error = SOCKERR_BIND; goto error; } else { bindOk = TRUE; break; } } if (!bindOk) { Warning(LGPFX "Failed to bind to privileged port for socket %d, " "no port available\n", fd); error = SOCKERR_BIND; Socket_Close(fd); goto error; } else { Debug(LGPFX "Successfully bound to port %d for socket %d\n", localAddr.svm_port, fd); } } if (connect(fd, (struct sockaddr *)&addr, addrLen) != 0) { sysErr = SocketGetLastError(); Warning(LGPFX "socket connect failed, error %d: %s\n", sysErr, Err_Errno2String(sysErr)); Socket_Close(fd); error = SOCKERR_CONNECT; goto error; } VMCISock_ReleaseAFValueFd(vsockDev); Debug(LGPFX "socket %d connected\n", fd); return fd; error: if (outError) { *outError = error; } VMCISock_ReleaseAFValueFd(vsockDev); return INVALID_SOCKET; }