Don't call from the plan-construction function, call after it returns.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
}
static inline bool doing_debug(void)
{
- return io_debug != NULL;
+ return io_debug_conn != NULL;
}
#else
static inline void set_current(struct io_conn *conn)
void *io_loop_return;
#ifdef DEBUG
-bool io_plan_for_other;
+/* Set to skip the next plan. */
+bool io_plan_nodebug;
+/* The current connection to apply plan to. */
struct io_conn *current;
-bool (*io_debug)(struct io_conn *conn);
+/* User-defined function to select which connection(s) to debug. */
+bool (*io_debug_conn)(struct io_conn *conn);
+/* Set when we wake up an connection we are debugging. */
bool io_debug_wakeup;
-void io_plan_debug(struct io_plan *plan)
+struct io_plan io_debug(struct io_plan plan)
{
- if (io_plan_for_other) {
- io_plan_for_other = false;
- return;
+ if (io_plan_nodebug) {
+ io_plan_nodebug = false;
+ return plan;
}
- if (!io_debug || !current)
- return;
+ if (!io_debug_conn || !current)
+ return plan;
- if (!io_debug(current) && !io_debug_wakeup)
- return;
+ if (!io_debug_conn(current) && !io_debug_wakeup)
+ return plan;
io_debug_wakeup = false;
- current->plan = *plan;
+ current->plan = plan;
backend_plan_changed(current);
/* Call back into the loop immediately. */
io_loop_return = io_loop();
+ return plan;
}
static void debug_io_wake(struct io_conn *conn)
{
/* We want linear if we wake a debugged connection, too. */
- if (io_debug && io_debug(conn))
+ if (io_debug_conn && io_debug_conn(conn))
io_debug_wakeup = true;
}
+
+/* Counterpart to io_plan_no_debug(), called in macros in io.h */
+static void io_plan_debug_again(void)
+{
+ io_plan_nodebug = false;
+}
#else
static void debug_io_wake(struct io_conn *conn)
{
}
+static void io_plan_debug_again(void)
+{
+}
#endif
struct io_listener *io_new_listener_(int fd,
{
struct io_conn *conn = malloc(sizeof(*conn));
+ io_plan_debug_again();
+
if (!conn)
return NULL;
{
struct io_conn *conn;
+ io_plan_debug_again();
+
assert(!old->duplex);
conn = malloc(sizeof(*conn));
plan.next_arg = arg;
plan.pollflag = POLLOUT;
- io_plan_debug(&plan);
return plan;
}
plan.next_arg = arg;
plan.pollflag = POLLIN;
- io_plan_debug(&plan);
return plan;
}
plan.next_arg = arg;
plan.pollflag = POLLIN;
- io_plan_debug(&plan);
return plan;
}
plan.next_arg = arg;
plan.pollflag = POLLOUT;
- io_plan_debug(&plan);
return plan;
}
-struct io_plan io_idle(void)
+struct io_plan io_idle_(void)
{
struct io_plan plan;
plan.pollflag = 0;
plan.io = NULL;
/* Never called (overridden by io_wake), but NULL means closing */
- plan.next = (void *)io_idle;
+ plan.next = (void *)io_idle_;
- io_plan_debug(&plan);
return plan;
}
void io_wake_(struct io_conn *conn, struct io_plan plan)
{
+ io_plan_debug_again();
+
/* It might be closing, but we haven't called its finish() yet. */
if (!conn->plan.next)
return;
}
/* Close the connection, we're done. */
-struct io_plan io_close(void)
+struct io_plan io_close_(void)
{
struct io_plan plan;
plan.next = NULL;
plan.u.close.saved_errno = errno;
- io_plan_debug(&plan);
return plan;
}
/* Exit the loop, returning this (non-NULL) arg. */
struct io_plan io_break_(void *ret, struct io_plan plan)
{
+ io_plan_debug_again();
+
assert(ret);
io_loop_return = ret;
* Returns NULL on error (and sets errno).
*/
#define io_new_conn(fd, plan) \
- (io_plan_other(), io_new_conn_((fd), (plan)))
+ (io_plan_no_debug(), io_new_conn_((fd), (plan)))
struct io_conn *io_new_conn_(int fd, struct io_plan plan);
/**
* Note that the I/O may actually be done immediately.
*/
#define io_write(data, len, cb, arg) \
- io_write_((data), (len), \
- typesafe_cb_preargs(struct io_plan, void *, \
- (cb), (arg), struct io_conn *), \
- (arg))
+ io_debug(io_write_((data), (len), \
+ typesafe_cb_preargs(struct io_plan, void *, \
+ (cb), (arg), struct io_conn *), \
+ (arg)))
struct io_plan io_write_(const void *data, size_t len,
struct io_plan (*cb)(struct io_conn *, void *),
void *arg);
* Note that the I/O may actually be done immediately.
*/
#define io_read(data, len, cb, arg) \
- io_read_((data), (len), \
- typesafe_cb_preargs(struct io_plan, void *, \
- (cb), (arg), struct io_conn *), \
- (arg))
+ io_debug(io_read_((data), (len), \
+ typesafe_cb_preargs(struct io_plan, void *, \
+ (cb), (arg), struct io_conn *), \
+ (arg)))
struct io_plan io_read_(void *data, size_t len,
struct io_plan (*cb)(struct io_conn *, void *),
void *arg);
* Note that the I/O may actually be done immediately.
*/
#define io_read_partial(data, len, cb, arg) \
- io_read_partial_((data), (len), \
- typesafe_cb_preargs(struct io_plan, void *, \
- (cb), (arg), struct io_conn *), \
- (arg))
+ io_debug(io_read_partial_((data), (len), \
+ typesafe_cb_preargs(struct io_plan, void *, \
+ (cb), (arg), \
+ struct io_conn *), \
+ (arg)))
struct io_plan io_read_partial_(void *data, size_t *len,
struct io_plan (*cb)(struct io_conn *, void *),
void *arg);
* Note that the I/O may actually be done immediately.
*/
#define io_write_partial(data, len, cb, arg) \
- io_write_partial_((data), (len), \
- typesafe_cb_preargs(struct io_plan, void *, \
- (cb), (arg), struct io_conn *), \
- (arg))
+ io_debug(io_write_partial_((data), (len), \
+ typesafe_cb_preargs(struct io_plan, void *, \
+ (cb), (arg), \
+ struct io_conn *), \
+ (arg)))
struct io_plan io_write_partial_(const void *data, size_t *len,
struct io_plan (*cb)(struct io_conn *, void*),
void *arg);
* This indicates the connection is idle: io_wake() will be called later do
* give the connection a new plan.
*/
-struct io_plan io_idle(void);
+#define io_idle() io_debug(io_idle_())
+struct io_plan io_idle_(void);
/**
* io_timeout - set timeout function if the callback doesn't complete.
* You must io_close() both of them to close the fd.
*/
#define io_duplex(conn, plan) \
- (io_plan_other(), io_duplex_((conn), (plan)))
+ (io_plan_no_debug(), io_duplex_((conn), (plan)))
struct io_conn *io_duplex_(struct io_conn *conn, struct io_plan plan);
/**
*
* This makes @conn ready to do I/O the next time around the io_loop().
*/
-#define io_wake(conn, plan) (io_plan_other(), io_wake_((conn), (plan)))
+#define io_wake(conn, plan) (io_plan_no_debug(), io_wake_((conn), (plan)))
void io_wake_(struct io_conn *conn, struct io_plan plan);
/**
*
* If io_loop() is called again, then @plan will be carried out.
*/
-#define io_break(ret, plan) (io_plan_other(), io_break_((ret), (plan)))
+#define io_break(ret, plan) (io_plan_no_debug(), io_break_((ret), (plan)))
struct io_plan io_break_(void *ret, struct io_plan plan);
/* FIXME: io_recvfrom/io_sendto */
*
* On return to io_loop, the connection will be closed.
*/
-struct io_plan io_close(void);
+#define io_close() io_debug(io_close_())
+struct io_plan io_close_(void);
/**
* io_close_cb - helper callback to close a connection.
#ifdef DEBUG
/**
- * io_debug - routine to select connection(s) to debug.
+ * io_debug_conn - routine to select connection(s) to debug.
*
* If this is set, the routine should return true if the connection is a
* debugging candidate. If so, the callchain for I/O operations on this
* connection will be linear, for easier use of a debugger.
*/
-extern bool (*io_debug)(struct io_conn *conn);
+extern bool (*io_debug_conn)(struct io_conn *conn);
/**
- * io_plan_other - mark the next plan not being for the current connection
+ * io_debug - if we're debugging the current connection, call immediately.
*
- * Most routines which take a plan are about to apply it to the current
- * connection. We (ab)use this pattern for debugging: as soon as such a
- * plan is created, it is called, to create a linear call chain.
- *
- * Some routines, like io_break() and io_wake() take an io_plan, but they
- * must not be applied immediately to the current connection, so we call this
- * first.
+ * This determines if we are debugging the current connection: if so,
+ * it immediately applies the plan and calls back into io_loop() to
+ * create a linear call chain.
*/
-#define io_plan_other() ((io_plan_for_other = true))
+struct io_plan io_debug(struct io_plan plan);
/**
- * io_plan_debug - hook for debugging a plan.
+ * io_plan_no_debug - mark the next plan not to be called immediately.
*
- * After constructing a plan, call this. If the current connection is being
- * debugged, then it will be immediately serviced with this plan.
+ * Most routines which take a plan are about to apply it to the current
+ * connection. We (ab)use this pattern for debugging: as soon as such a
+ * plan is created it is called, to create a linear call chain.
+ *
+ * Some routines, like io_break(), io_duplex() and io_wake() take an
+ * io_plan, but they must not be applied immediately to the current
+ * connection, so we call this first.
*/
-void io_plan_debug(struct io_plan *plan);
-extern bool io_plan_for_other;
+#define io_plan_no_debug() ((io_plan_nodebug = true))
+
+extern bool io_plan_nodebug;
#else
-#define io_plan_other() (void)0
-static inline void io_plan_debug(struct io_plan *plan) { }
+static inline struct io_plan io_debug(struct io_plan plan)
+{
+ return plan;
+}
+#define io_plan_no_debug() (void)0
#endif
#endif /* CCAN_IO_PLAN_H */
#include "run-01-start-finish.c"
#undef main
static bool always_debug(struct io_conn *conn) { return true; }
-int main(void) { io_debug = always_debug; return real_main(); }
+int main(void) { io_debug_conn = always_debug; return real_main(); }
#include "run-02-read.c"
#undef main
static bool always_debug(struct io_conn *conn) { return true; }
-int main(void) { io_debug = always_debug; return real_main(); }
+int main(void) { io_debug_conn = always_debug; return real_main(); }
#include "run-03-readpartial.c"
#undef main
static bool always_debug(struct io_conn *conn) { return true; }
-int main(void) { io_debug = always_debug; return real_main(); }
+int main(void) { io_debug_conn = always_debug; return real_main(); }
#include "run-04-writepartial.c"
#undef main
static bool always_debug(struct io_conn *conn) { return true; }
-int main(void) { io_debug = always_debug; return real_main(); }
+int main(void) { io_debug_conn = always_debug; return real_main(); }
#include "run-05-write.c"
#undef main
static bool always_debug(struct io_conn *conn) { return true; }
-int main(void) { io_debug = always_debug; return real_main(); }
+int main(void) { io_debug_conn = always_debug; return real_main(); }
#include "run-06-idle.c"
#undef main
static bool always_debug(struct io_conn *conn) { return true; }
-int main(void) { io_debug = always_debug; return real_main(); }
+int main(void) { io_debug_conn = always_debug; return real_main(); }
#include "run-07-break.c"
#undef main
static bool always_debug(struct io_conn *conn) { return true; }
-int main(void) { io_debug = always_debug; return real_main(); }
+int main(void) { io_debug_conn = always_debug; return real_main(); }
#include "run-08-hangup-on-idle.c"
#undef main
static bool always_debug(struct io_conn *conn) { return true; }
-int main(void) { io_debug = always_debug; return real_main(); }
+int main(void) { io_debug_conn = always_debug; return real_main(); }
#include "run-08-read-after-hangup.c"
#undef main
static bool always_debug(struct io_conn *conn) { return true; }
-int main(void) { io_debug = always_debug; return real_main(); }
+int main(void) { io_debug_conn = always_debug; return real_main(); }
{
return conn == buf[1].reader;
}
-int main(void) { io_debug = debug_one; return real_main(); }
+int main(void) { io_debug_conn = debug_one; return real_main(); }
#include "run-12-bidir.c"
#undef main
static bool always_debug(struct io_conn *conn) { return true; }
-int main(void) { io_debug = always_debug; return real_main(); }
+int main(void) { io_debug_conn = always_debug; return real_main(); }
#include "run-13-all-idle.c"
#undef main
static bool always_debug(struct io_conn *conn) { return true; }
-int main(void) { io_debug = always_debug; return real_main(); }
+int main(void) { io_debug_conn = always_debug; return real_main(); }
#include "run-15-timeout.c"
#undef main
static bool always_debug(struct io_conn *conn) { return true; }
-int main(void) { io_debug = always_debug; return real_main(); }
+int main(void) { io_debug_conn = always_debug; return real_main(); }
#include "run-17-homemade-io.c"
#undef main
static bool always_debug(struct io_conn *conn) { return true; }
-int main(void) { io_debug = always_debug; return real_main(); }
+int main(void) { io_debug_conn = always_debug; return real_main(); }
plan.next_arg = arg;
plan.pollflag = POLLIN;
- io_plan_debug(&plan);
return plan;
}
#include "run-18-errno.c"
#undef main
static bool always_debug(struct io_conn *conn) { return true; }
-int main(void) { io_debug = always_debug; return real_main(); }
+int main(void) { io_debug_conn = always_debug; return real_main(); }