sp_close waits for endpoints termination
Signed-off-by: Martin Sustrik <sustrik@250bpm.com>
diff --git a/src/core/ctx.c b/src/core/ctx.c
index 46e9f8f..259963f 100644
--- a/src/core/ctx.c
+++ b/src/core/ctx.c
@@ -335,21 +335,16 @@
{
SP_BASIC_CHECKS;
- sp_mutex_lock (&self.sync);
-
/* Deallocate the socket object. */
- sp_sock_close (self.socks [s]);
-
- /* sp_sock_close may actually deallocate the socket. Do not use the
- pointer anymore. */
- self.socks [s] = NULL;
+ sp_sock_term (self.socks [s]);
/* If there's sp_term() waiting for all sockets being closed and this is
the last open socket let library termination proceed. */
+ sp_mutex_lock (&self.sync);
+ self.socks [s] = NULL;
--self.nsocks;
if (self.zombie && self.nsocks == 0)
sp_cond_post (&self.termcond);
-
sp_mutex_unlock (&self.sync);
return 0;
diff --git a/src/core/sock.c b/src/core/sock.c
index 507c46e..498629d 100644
--- a/src/core/sock.c
+++ b/src/core/sock.c
@@ -32,9 +32,6 @@
#define SP_SOCK_EVENT_IN 1
#define SP_SOCK_EVENT_OUT 2
-/* Private functions. */
-static void sp_sockbase_destroy (struct sp_sockbase *self);
-
void sp_sockbase_init (struct sp_sockbase *self,
const struct sp_sockbase_vfptr *vfptr, int fd)
{
@@ -67,15 +64,18 @@
sp_cp_unlock (&sockbase->cp);
}
-void sp_sock_close (struct sp_sock *self)
+void sp_sock_term (struct sp_sock *self)
{
+ int rc;
struct sp_sockbase *sockbase;
struct sp_list_item *it;
struct sp_epbase *ep;
sockbase = (struct sp_sockbase*) self;
- /* Ask all the associated endpoints to terminate. Call to close(ep) can
+ sp_cp_lock (&sockbase->cp);
+
+ /* Ask all the associated endpoints to terminate. Call to sp_ep_close can
actually deallocate the endpoint, so take care to get pointer to the
next endpoint before the call. */
it = sp_list_begin (&sockbase->eps);
@@ -85,27 +85,30 @@
sp_ep_close ((void*) ep);
}
- /* If there are no active endpoints we can deallocate the socket
- straight away. */
- if (sp_list_empty (&sockbase->eps)) {
- sp_sockbase_destroy (sockbase);
- return;
+ while (1) {
+
+ /* If there are no active endpoints we can deallocate the socket
+ straight away. */
+ if (sp_list_empty (&sockbase->eps)) {
+
+ /* Terminate the sp_sockbase itself. */
+ sp_cp_unlock (&sockbase->cp);
+ sp_list_term (&sockbase->eps);
+ sp_clock_term (&sockbase->clock);
+ sp_cond_term (&sockbase->cond);
+ sp_cp_term (&sockbase->cp);
+
+ /* Deallocate the derived class. */
+ sockbase->vfptr->destroy (sockbase);
+
+ return;
+ }
+
+ /* Wait till all the endpoints are closed. */
+ sp_cond_set_timeout (&sockbase->cond, -1);
+ rc = sp_cond_wait (&sockbase->cond, &sockbase->cp.sync);
+ errnum_assert (rc == 0, rc);
}
-
- /* Mark the socket as in process of terminating. */
- sockbase->flags |= SP_SOCK_FLAG_CLOSED;
-}
-
-static void sp_sockbase_destroy (struct sp_sockbase *self)
-{
- /* Terminate the sp_sockbase itself. */
- sp_list_term (&self->eps);
- sp_clock_term (&self->clock);
- sp_cond_term (&self->cond);
- sp_cp_term (&self->cp);
-
- /* Deallocate the derived class. */
- self->vfptr->destroy (self);
}
void sp_sockbase_unblock_recv (struct sp_sockbase *self)
@@ -350,10 +353,10 @@
/* Remove the endpoint from the list of active endpoints. */
sp_list_erase (&sockbase->eps, &ep->item);
- /* When last endpoint terminates, socket can be deallocated as well. */
- if ((sockbase->flags & SP_SOCK_FLAG_CLOSED) &&
- sp_list_empty (&sockbase->eps))
- sp_sockbase_destroy (sockbase);
+ /* sp_close() may be waiting for termination of this endpoint.
+ Send it a signal. */
+ if (sp_list_empty (&sockbase->eps))
+ sp_cond_post (&sockbase->cond);
}
int sp_sock_send (struct sp_sock *self, const void *buf, size_t len, int flags)
diff --git a/src/core/sock.h b/src/core/sock.h
index e17d6a2..ac93159 100644
--- a/src/core/sock.h
+++ b/src/core/sock.h
@@ -31,7 +31,7 @@
void sp_sock_zombify (struct sp_sock *self);
/* Called by sp_close(). */
-void sp_sock_close (struct sp_sock *self);
+void sp_sock_term (struct sp_sock *self);
/* Returns default completion port associated with the socket. */
struct sp_cp *sp_sock_getcp (struct sp_sock *self);
diff --git a/src/protocol.h b/src/protocol.h
index b6a3aa3..e84d8ff 100644
--- a/src/protocol.h
+++ b/src/protocol.h
@@ -66,7 +66,6 @@
};
#define SP_SOCK_FLAG_ZOMBIE 1
-#define SP_SOCK_FLAG_CLOSED 2
struct sp_sockbase
{