~ We like to free everything on exit, so valgrind doesn't complain (valgrind * is an awesome runtime memory usage detector for C and C++ programs). In * some ways it would be neater not to do this, but it turns out some * transient objects still need cleaning. */
| 601 | * some ways it would be neater not to do this, but it turns out some |
| 602 | * transient objects still need cleaning. */ |
| 603 | static void free_all_channels(struct lightningd *ld) |
| 604 | { |
| 605 | struct peer *p; |
| 606 | struct peer_node_id_map_iter it; |
| 607 | |
| 608 | /*~ tal supports *destructors* using `tal_add_destructor()`; the most |
| 609 | * common use is for an object to delete itself from a linked list |
| 610 | * when it's freed. |
| 611 | * |
| 612 | * As a result, freeing an object (which frees any tal objects |
| 613 | * allocated off it, and any allocated off them, etc) may cause |
| 614 | * callbacks; in this case, some objects freed here can cause database |
| 615 | * writes, which must be inside a transaction. */ |
| 616 | db_begin_transaction(ld->wallet->db); |
| 617 | |
| 618 | /* Now we free all the HTLCs */ |
| 619 | free_htlcs(ld, NULL); |
| 620 | |
| 621 | /*~ For every peer, we free every channel. On allocation the peer was |
| 622 | * given a destructor (`destroy_peer`) which removes itself from the |
| 623 | * hashtable. |
| 624 | * |
| 625 | * Deletion from a hashtable during iteration is safe and consistent. |
| 626 | * Adding is forbidden, hence the lock() function which causes that to |
| 627 | * assert. |
| 628 | */ |
| 629 | peer_node_id_map_lock(ld->peers); |
| 630 | for (p = peer_node_id_map_first(ld->peers, &it); |
| 631 | p; |
| 632 | p = peer_node_id_map_next(ld->peers, &it)) { |
| 633 | struct channel *c; |
| 634 | |
| 635 | /*~ A peer can have multiple channels. */ |
| 636 | while ((c = list_top(&p->channels, struct channel, list)) |
| 637 | != NULL) { |
| 638 | /* Removes itself from list as we free it */ |
| 639 | tal_free(c); |
| 640 | } |
| 641 | |
| 642 | /* A peer may have a channel in the process of opening. */ |
| 643 | if (p->uncommitted_channel) { |
| 644 | struct uncommitted_channel *uc = p->uncommitted_channel; |
| 645 | |
| 646 | /* Setting to NULL stops destroy_uncommitted_channel |
| 647 | * from trying to remove peer from db! */ |
| 648 | p->uncommitted_channel = NULL; |
| 649 | tal_free(uc); |
| 650 | } |
| 651 | /* Removes itself from htable as we free it */ |
| 652 | tal_free(p); |
| 653 | } |
| 654 | peer_node_id_map_unlock(ld->peers); |
| 655 | |
| 656 | /*~ Commit the transaction. Note that the db is actually |
| 657 | * single-threaded, so commits never fail and we don't need |
| 658 | * spin-and-retry logic everywhere. */ |
| 659 | db_commit_transaction(ld->wallet->db); |
| 660 | } |
no test coverage detected