@@ -103,7 +103,7 @@ static void close_peer_io_timeout(struct peer *peer)
103
103
104
104
static void close_subd_timeout (struct subd * subd )
105
105
{
106
- status_peer_debug (& subd -> peer -> id , "Subd did not close, forcing close" );
106
+ status_peer_broken (& subd -> peer -> id , "Subd did not close, forcing close" );
107
107
io_close (subd -> conn );
108
108
}
109
109
@@ -118,7 +118,7 @@ static void drain_peer(struct peer *peer)
118
118
assert (tal_count (peer -> subds ) == 0 );
119
119
120
120
/* You have five seconds to drain. */
121
- peer -> draining = true ;
121
+ peer -> draining_state = WRITING_TO_PEER ;
122
122
status_peer_debug (& peer -> id , "disconnect_peer: draining with 5 second timer." );
123
123
notleak (new_reltimer (& peer -> daemon -> timers ,
124
124
peer -> to_peer , time_from_sec (5 ),
@@ -131,19 +131,33 @@ static void drain_peer(struct peer *peer)
131
131
132
132
void disconnect_peer (struct peer * peer )
133
133
{
134
- /* Free all the subds immediately */
134
+ peer -> draining_state = READING_FROM_SUBDS ;
135
+
135
136
for (size_t i = 0 ; i < tal_count (peer -> subds ); i ++ ) {
136
- /* Once conn exists, subd is a child of the conn. Free conn, free subd. */
137
+ /* Start timer in case it doesn't close by itself */
137
138
if (peer -> subds [i ]-> conn ) {
138
- tal_del_destructor (peer -> subds [i ], destroy_connected_subd );
139
- tal_free (peer -> subds [i ]-> conn );
139
+ status_peer_debug (& peer -> id , "disconnect_peer: setting 5 second timer for subd %zu/%zu." ,
140
+ i , tal_count (peer -> subds ));
141
+ notleak (new_reltimer (& peer -> daemon -> timers , peer -> subds [i ],
142
+ time_from_sec (5 ),
143
+ close_subd_timeout , peer -> subds [i ]));
140
144
} else {
141
145
/* We told lightningd that peer spoke, but it hasn't returned yet. */
142
- tal_free (peer -> subds [i ]);
146
+ tal_arr_remove (& peer -> subds , i );
147
+ i -- ;
143
148
}
144
149
}
145
- tal_resize (& peer -> subds , 0 );
146
- drain_peer (peer );
150
+
151
+ if (tal_count (peer -> subds ) != 0 ) {
152
+ status_peer_debug (& peer -> id , "disconnect_peer: waking %zu subds." ,
153
+ tal_count (peer -> subds ));
154
+ /* Wake them up so we read again */
155
+ io_wake (& peer -> subds );
156
+ } else {
157
+ status_peer_debug (& peer -> id , "disconnect_peer: no subds, draining now." );
158
+ /* No subds left, start draining peer */
159
+ drain_peer (peer );
160
+ }
147
161
}
148
162
149
163
/* Send warning, close connection to peer */
@@ -162,6 +176,18 @@ static void send_warning(struct peer *peer, const char *fmt, ...)
162
176
163
177
inject_peer_msg (peer , take (msg ));
164
178
179
+ /* Free all the subds immediately */
180
+ for (size_t i = 0 ; i < tal_count (peer -> subds ); i ++ ) {
181
+ /* Once conn exists, subd is a child of the conn. Free conn, free subd. */
182
+ if (peer -> subds [i ]-> conn ) {
183
+ tal_del_destructor (peer -> subds [i ], destroy_connected_subd );
184
+ tal_free (peer -> subds [i ]-> conn );
185
+ } else {
186
+ /* We told lightningd that peer spoke, but it hasn't returned yet. */
187
+ tal_free (peer -> subds [i ]);
188
+ }
189
+ }
190
+ tal_resize (& peer -> subds , 0 );
165
191
disconnect_peer (peer );
166
192
}
167
193
@@ -1061,7 +1087,7 @@ static struct io_plan *write_to_peer(struct io_conn *peer_conn,
1061
1087
/* Still nothing to send? */
1062
1088
if (!msg ) {
1063
1089
/* Draining? Shutdown socket (to avoid losing msgs) */
1064
- if (peer -> draining ) {
1090
+ if (peer -> draining_state == WRITING_TO_PEER ) {
1065
1091
status_peer_debug (& peer -> id , "draining done, shutting down" );
1066
1092
io_wake (& peer -> peer_in );
1067
1093
return io_sock_shutdown (peer_conn );
@@ -1080,7 +1106,7 @@ static struct io_plan *write_to_peer(struct io_conn *peer_conn,
1080
1106
}
1081
1107
}
1082
1108
1083
- if (peer -> draining )
1109
+ if (peer -> draining_state == WRITING_TO_PEER )
1084
1110
status_peer_debug (& peer -> id , "draining, but sending %s." ,
1085
1111
peer_wire_name (fromwire_peektype (msg )));
1086
1112
@@ -1170,10 +1196,14 @@ static void destroy_connected_subd(struct subd *subd)
1170
1196
* have been waiting for write_to_subd) */
1171
1197
io_wake (& peer -> peer_in );
1172
1198
1173
- /* If neither peer nor subds, we're done */
1174
- if (tal_count (peer -> subds ) == 0 && !peer -> to_peer ) {
1175
- tal_free (peer );
1176
- return ;
1199
+ if (tal_count (peer -> subds ) == 0 ) {
1200
+ if (!peer -> to_peer ) {
1201
+ /* Nothing left */
1202
+ tal_free (peer );
1203
+ } else if (peer -> draining_state == READING_FROM_SUBDS ) {
1204
+ /* We've finished draining subds, start draining peer */
1205
+ drain_peer (peer );
1206
+ }
1177
1207
}
1178
1208
}
1179
1209
@@ -1242,7 +1272,7 @@ static struct io_plan *read_body_from_peer_done(struct io_conn *peer_conn,
1242
1272
peer -> last_recv_time = time_now ();
1243
1273
1244
1274
/* Don't process packets while we're closing */
1245
- if (peer -> draining )
1275
+ if (peer -> draining_state != NOT_DRAINING )
1246
1276
return next_read (peer_conn , peer );
1247
1277
1248
1278
/* If we swallow this, just try again. */
@@ -1464,7 +1494,7 @@ void peer_connect_subd(struct daemon *daemon, const u8 *msg, int fd)
1464
1494
}
1465
1495
1466
1496
/* Could be disconnecting now */
1467
- if (!peer -> to_peer || peer -> draining ) {
1497
+ if (!peer -> to_peer || peer -> draining_state != NOT_DRAINING ) {
1468
1498
close (fd );
1469
1499
return ;
1470
1500
}
0 commit comments