mirror of
https://github.com/Ride-The-Lightning/RTL.git
synced 2026-08-13 12:33:07 +02:00
Address review: protect the fire-and-forget channel close from the timeout
LND's DELETE /v1/channels/{channelPoint} streams until the closing tx
confirms, routinely longer than the wrapper's 10-minute bound. The
close call in closeChannel is fire-and-forget (202 returned
immediately, no .catch), so the timeout rejection would have become an
unhandled promise rejection and crashed the process ~10 minutes after
any close that had not yet confirmed. request-promise returned
Bluebird promises whose unhandled rejections only warned, which is why
this never crashed before.
The close now uses a copy of the options with timeout: 0 (same
treatment as the invoice/payment subscriptions) and a .catch that logs
through handleError - errors were never surfaced to the HTTP response
anyway, but logging beats Bluebird's silent warning. This was the only
call site without a rejection handler.
Verified on the fixture: opened a disposable 200k alice->bob channel
via RTL, closed it (202, gone from open and listed in closed after
mining), then requested a close for a bogus channel point - LND
rejects the stream, the catch logs the error (no auth headers in it),
and the process stays up. Read suite re-passes.
This commit is contained in:
parent
5d1f55a9c6
commit
19aa332d61
2 changed files with 14 additions and 2 deletions
|
|
@ -175,7 +175,13 @@ export const closeChannel = (req, res, next) => {
|
|||
options.url = options.url + '&sat_per_vbyte=' + req.query.sat_per_vbyte;
|
||||
}
|
||||
logger.log({ selectedNode: req.session.selectedNode, level: 'DEBUG', fileName: 'Channels', msg: 'Closing Channel Options URL', data: options.url });
|
||||
request.delete(options);
|
||||
// Fire-and-forget: LND keeps the close stream open until the closing tx
|
||||
// confirms, so exempt it from the request timeout; the 202 is already sent,
|
||||
// so log a rejection instead of letting it crash the process.
|
||||
request.delete({ ...options, timeout: 0 }).catch((errRes) => {
|
||||
const err = common.handleError(errRes, 'Channels', 'Close Channel Error', req.session.selectedNode);
|
||||
logger.log({ selectedNode: req.session.selectedNode, level: 'ERROR', fileName: 'Channels', msg: 'Close Channel Error', error: err });
|
||||
});
|
||||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'Channels', msg: 'Channel Close Requested' });
|
||||
res.status(202).json({ message: 'Close channel request has been submitted.' });
|
||||
}
|
||||
|
|
|
|||
|
|
@ -169,7 +169,13 @@ export const closeChannel = (req, res, next) => {
|
|||
if (req.query.target_conf) { options.url = options.url + '&target_conf=' + req.query.target_conf; }
|
||||
if (req.query.sat_per_vbyte) { options.url = options.url + '&sat_per_vbyte=' + req.query.sat_per_vbyte; }
|
||||
logger.log({ selectedNode: req.session.selectedNode, level: 'DEBUG', fileName: 'Channels', msg: 'Closing Channel Options URL', data: options.url });
|
||||
request.delete(options);
|
||||
// Fire-and-forget: LND keeps the close stream open until the closing tx
|
||||
// confirms, so exempt it from the request timeout; the 202 is already sent,
|
||||
// so log a rejection instead of letting it crash the process.
|
||||
request.delete({ ...options, timeout: 0 }).catch((errRes) => {
|
||||
const err = common.handleError(errRes, 'Channels', 'Close Channel Error', req.session.selectedNode);
|
||||
logger.log({ selectedNode: req.session.selectedNode, level: 'ERROR', fileName: 'Channels', msg: 'Close Channel Error', error: err });
|
||||
});
|
||||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'Channels', msg: 'Channel Close Requested' });
|
||||
res.status(202).json({ message: 'Close channel request has been submitted.' });
|
||||
} catch (error: any) {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue