+ if (c->plan[IO_OUT].status == IO_WAITING
+ && c->plan[IO_OUT].arg.u1.const_vp == wait)
+ io_do_wakeup(c, IO_OUT);
+ }
+}
+
+static void destroy_conn(struct io_conn *conn, bool close_fd)
+{
+ int saved_errno = errno;
+
+ if (close_fd)
+ close(conn->fd.fd);
+ del_fd(&conn->fd);
+
+ remove_from_always(&conn->plan[IO_IN]);
+ remove_from_always(&conn->plan[IO_OUT]);
+
+ /* errno saved/restored by tal_free itself. */
+ if (conn->finish) {
+ errno = saved_errno;
+ conn->finish(conn, conn->finish_arg);
+ }
+}
+
+static void destroy_conn_close_fd(struct io_conn *conn)
+{
+ destroy_conn(conn, true);
+}
+
+bool add_conn(struct io_conn *c)
+{
+ if (!add_fd(&c->fd, 0))
+ return false;
+ tal_add_destructor(c, destroy_conn_close_fd);
+ return true;
+}
+
+void cleanup_conn_without_close(struct io_conn *conn)
+{
+ tal_del_destructor(conn, destroy_conn_close_fd);
+ destroy_conn(conn, false);