some shutdowns can fail, so the function needs to return an rcode.
the destructors should just call the shutdown, so the caller can
just talloc_free() things, and have it all work properly.
the shutdown doesn't need to reset the destructors, as the main
fr_bio_shutdown() will do that.
*/
int fr_bio_shutdown(fr_bio_t *bio)
{
+ int rcode;
fr_bio_t *this, *first;
fr_bio_common_t *my;
my = (fr_bio_common_t *) this;
if (my->priv_cb.shutdown) {
- my->priv_cb.shutdown(&my->bio);
+ rcode = my->priv_cb.shutdown(&my->bio);
+ if (rcode < 0) return rcode;
my->priv_cb.shutdown = NULL;
}
*/
my = (fr_bio_common_t *) first;
- if (my->cb.shutdown) my->cb.shutdown(first);
- my->cb.shutdown = NULL;
+ if (my->cb.shutdown) {
+ rcode = my->cb.shutdown(first);
+ if (rcode < 0) return rcode;
+ my->cb.shutdown = NULL;
+ }
return 0;
}
typedef struct {
fr_bio_callback_t connected; //!< called when the BIO is ready to be used
- fr_bio_callback_t shutdown; //!< called when the BIO is being shut down
+ fr_bio_io_t shutdown; //!< called when the BIO is being shut down
fr_bio_callback_t eof; //!< called when the BIO is at EOF
fr_bio_callback_t failed; //!< called when the BIO fails
#define _BIO_PRIVATE 1
#include <freeradius-devel/bio/base.h>
-typedef int (*fr_bio_shutdown_t)(fr_bio_t *bio);
-
typedef struct fr_bio_common_s fr_bio_common_t;
typedef struct {
fr_bio_io_t connected;
- fr_bio_callback_t shutdown;
+ fr_bio_io_t shutdown;
fr_bio_io_t eof;
fr_bio_callback_t failed;
addr->socket.inet.ifindex = my->info.socket.inet.ifindex; \
} while (0)
-/*
- * Close the descriptor and free the bio.
+/** Orderly shutdown.
+ *
*/
-static int fr_bio_fd_destructor(fr_bio_fd_t *my)
+static int fr_bio_fd_shutdown(fr_bio_t *bio)
{
- /*
- * The upstream bio must have unlinked it from the chain before calling talloc_free() on this
- * bio.
- */
- fr_assert(!fr_bio_prev(&my->bio));
- fr_assert(!fr_bio_next(&my->bio));
+ fr_bio_fd_t *my = talloc_get_type_abort(bio, fr_bio_fd_t);
+
+ if (my->info.state == FR_BIO_FD_STATE_CLOSED) return 0;
FR_TIMER_DELETE(&my->connect.ev);
if (my->connect.el) {
return fr_bio_fd_close(&my->bio);
}
-/** Orderly shutdown.
- *
- */
-static void fr_bio_fd_shutdown(fr_bio_t *bio)
+static int fr_bio_fd_destructor(fr_bio_fd_t *my)
{
- fr_bio_fd_t *my = talloc_get_type_abort(bio, fr_bio_fd_t);
-
- (void) fr_bio_fd_destructor(my);
- talloc_set_destructor(my, NULL);
+ return fr_bio_fd_shutdown((fr_bio_t *) my);
}
static int fr_bio_fd_eof(fr_bio_t *bio)
return 0;
}
-static void fr_bio_fd_unix_shutdown(fr_bio_t *bio)
+static int fr_bio_fd_unix_shutdown(fr_bio_t *bio)
{
fr_bio_fd_t *my = talloc_get_type_abort(bio, fr_bio_fd_t);
/*
* Run the user shutdown before we run ours.
*/
- if (my->user_shutdown) my->user_shutdown(bio);
+ if (my->user_shutdown) {
+ int rcode;
- (void) unlink(my->info.socket.unix.path);
+ rcode = my->user_shutdown(bio);
+ if (rcode < 0) return rcode;
+ }
+
+ if (unlink(my->info.socket.unix.path) < 0) return fr_bio_error(GENERIC);
+
+ return 0;
}
/** Bind to a Unix domain socket.
*/
typedef struct fr_bio_fd_s {
FR_BIO_COMMON;
- fr_bio_callback_t user_shutdown; //!< user shutdown
+ fr_bio_io_t user_shutdown; //!< user shutdown
fr_bio_fd_info_t info;
my->cb.connected(my);
}
-static void fr_bio_packet_shutdown(fr_bio_t *bio)
+static int fr_bio_packet_shutdown(fr_bio_t *bio)
{
fr_bio_packet_t *my = bio->uctx;
- if (my->cb.shutdown) my->cb.shutdown(my);
- my->cb.shutdown = NULL;
+ if (!my->cb.shutdown) return 0;
+
+ return my->cb.shutdown(my);
}
static void fr_bio_packet_eof(fr_bio_t *bio)
typedef struct {
fr_bio_packet_callback_t connected;
- fr_bio_packet_callback_t shutdown;
+ fr_bio_packet_io_t shutdown;
fr_bio_packet_callback_t eof;
fr_bio_packet_callback_t failed;
/** Shutdown callback.
*
*/
-static void fr_bio_pipe_shutdown(fr_bio_t *bio)
+static int fr_bio_pipe_shutdown(fr_bio_t *bio)
{
+ int rcode;
fr_bio_pipe_t *my = talloc_get_type_abort(bio, fr_bio_pipe_t);
fr_assert(my->next != NULL);
pthread_mutex_lock(&my->mutex);
- fr_bio_shutdown(my->next);
+ rcode = fr_bio_shutdown(my->next);
pthread_mutex_unlock(&my->mutex);
+
+ return rcode;
}
/** Set EOF.
*
* Cancel / close has to be called before re-init.
*/
-static void fr_bio_queue_shutdown(fr_bio_t *bio)
+static int fr_bio_queue_shutdown(fr_bio_t *bio)
{
fr_bio_queue_t *my = talloc_get_type_abort(bio, fr_bio_queue_t);
fr_bio_queue_list_cancel(my);
+
+ return 0;
}
return &item->retry;
}
-
-/** Cancel all outstanding packets.
+/** Orderly shutdown.
*
*/
-static int fr_bio_retry_destructor(fr_bio_retry_t *my)
+static int fr_bio_retry_shutdown(fr_bio_t *bio)
{
+ fr_bio_retry_t *my = talloc_get_type_abort(bio, fr_bio_retry_t);
fr_bio_retry_entry_t *item;
fr_timer_list_disarm(my->next_tl);
return 0;
}
-/** Orderly shutdown.
- *
- */
-static void fr_bio_retry_shutdown(fr_bio_t *bio)
+static int fr_bio_retry_destructor(fr_bio_retry_t *my)
{
- fr_bio_retry_t *my = talloc_get_type_abort(bio, fr_bio_retry_t);
-
- (void) fr_bio_retry_destructor(my);
- talloc_set_destructor(my, NULL);
+ return fr_bio_retry_shutdown((fr_bio_t *) my);
}
/** Allocate a #fr_bio_retry_t