int ftw_socket_inbox_shutdown(struct ftw_socket_inbox ** const sock) { uint64_t time; double elapsed_time; int rc; /* Preconditions expected of LabVIEW. */ ftw_assert(sock); if (*sock == NULL) { errno = EBADF; return -1; } time = uv_hrtime(); rc = nn_close((*sock)->id); nn_sem_post(&(*sock)->deinitialized); nn_thread_term(&(*sock)->async_recv_thread); nn_sem_term(&(*sock)->msg_acknowledged); nn_sem_term(&(*sock)->initialized); nn_sem_term(&(*sock)->deinitialized); time = uv_hrtime() - time; elapsed_time = time / 1000000000.0; ftw_debug("Inbox Shutdown time: %.3fsec", elapsed_time); return rc; }
int nn_sock_term (struct nn_sock *self) { int rc; int i; /* NOTE: nn_sock_stop must have already been called. */ /* Some endpoints may still be alive. Here we are going to wait till they are all closed. This loop is not interruptible, because making it so would leave a partially cleaned up socket, and we don't have a way to defer resource deallocation. */ for (;;) { rc = nn_sem_wait (&self->termsem); if (nn_slow (rc == -EINTR)) continue; errnum_assert (rc == 0, -rc); break; } /* Also, wait for all holds on the socket to be released. */ for (;;) { rc = nn_sem_wait (&self->relesem); if (nn_slow (rc == -EINTR)) continue; errnum_assert (rc == 0, -rc); break; } /* Threads that posted the semaphore(s) can still have the ctx locked for a short while. By simply entering the context and exiting it immediately we can be sure that any such threads have already exited the context. */ nn_ctx_enter (&self->ctx); nn_ctx_leave (&self->ctx); /* At this point, we can be reasonably certain that no other thread has any references to the socket. */ nn_fsm_stopped_noevent (&self->fsm); nn_fsm_term (&self->fsm); nn_sem_term (&self->termsem); nn_list_term (&self->sdeps); nn_list_term (&self->eps); nn_clock_term (&self->clock); nn_ctx_term (&self->ctx); /* Destroy any optsets associated with the socket. */ for (i = 0; i != NN_MAX_TRANSPORT; ++i) if (self->optsets [i]) self->optsets [i]->vfptr->destroy (self->optsets [i]); return 0; }
int ftw_socket_close(struct ftw_socket * const sock) { int rc; /* Preconditions expected of LabVIEW. */ ftw_assert(sock); rc = nn_close(sock->id); if (rc != 0) { return rc; } /* A non-NULL Dynamic Event Reference means this socket has an asynchronous recv thread that must shut down. */ if (sock->incoming_msg_notifier_event) { nn_thread_term(&sock->async_recv_thread); nn_sem_term(&sock->async_recv_ready); nn_sem_term(&sock->msg_acknowledged); } return 0; }
int nn_sock_term (struct nn_sock *self) { int rc; int i; /* Ask the state machine to start closing the socket. */ nn_ctx_enter (&self->ctx); nn_fsm_stop (&self->fsm); nn_ctx_leave (&self->ctx); /* Shutdown process was already started but some endpoints may still alive. Here we are going to wait till they are all closed. */ rc = nn_sem_wait (&self->termsem); if (nn_slow (rc == -EINTR)) return -EINTR; errnum_assert (rc == 0, -rc); /* The thread that posted the semaphore can still have the ctx locked for a short while. By simply entering the context and exiting it immediately we can be sure that the thread in question have already exited the context. */ nn_ctx_enter (&self->ctx); nn_ctx_leave (&self->ctx); /* Deallocate the resources. */ nn_fsm_stopped_noevent (&self->fsm); nn_fsm_term (&self->fsm); nn_sem_term (&self->termsem); nn_list_term (&self->sdeps); nn_list_term (&self->eps); nn_clock_term (&self->clock); nn_ctx_term (&self->ctx); /* Destroy any optsets associated with the socket. */ for (i = 0; i != NN_MAX_TRANSPORT; ++i) if (self->optsets [i]) self->optsets [i]->vfptr->destroy (self->optsets [i]); return 0; }