daemon: exit main loop to free dead peers.

When a peer is finally to be freed (ie. STATE_CLOSED), doing this
inside the state logic is a bit fraught.  We're better off exiting the
io loop and freeing it there.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
This commit is contained in:
Rusty Russell 2016-01-22 06:45:28 +10:30
parent f690be1e83
commit 45c5c83d6f
2 changed files with 20 additions and 6 deletions

View File

@ -196,7 +196,6 @@ static void tal_freefn(void *ptr)
int main(int argc, char *argv[]) int main(int argc, char *argv[])
{ {
struct lightningd_state *dstate = lightningd_state(); struct lightningd_state *dstate = lightningd_state();
struct timer *expired;
unsigned int portnum = 0; unsigned int portnum = 0;
err_set_progname(argv[0]); err_set_progname(argv[0]);
@ -261,13 +260,24 @@ int main(int argc, char *argv[])
log_info(dstate->base_log, "Hello world!"); log_info(dstate->base_log, "Hello world!");
/* If io_loop returns NULL, either a timer expired, or all fds closed */ for (;;) {
while (!io_loop(&dstate->timers, &expired) && expired) { struct timer *expired;
struct timeout *to; void *v = io_loop(&dstate->timers, &expired);
/* We use io_break(dstate) to shut down. */
if (v == dstate)
break;
/* We use it on a peer when it needs freeing (may be
* NULL if we only broke out due to timer). */
tal_free(v);
if (expired) {
struct timeout *to;
to = container_of(expired, struct timeout, timer); to = container_of(expired, struct timeout, timer);
to->cb(to->arg); to->cb(to->arg);
} }
}
tal_free(dstate); tal_free(dstate);
opt_free_table(); opt_free_table();

View File

@ -160,6 +160,10 @@ static void state_single(struct peer *peer,
state_name(peer->state)); state_name(peer->state));
fatal("Peer entered error state"); fatal("Peer entered error state");
} }
/* Break out and free this peer if it's completely done. */
if (peer->state == STATE_CLOSED)
io_break(peer);
} }
static void try_command(struct peer *peer) static void try_command(struct peer *peer)