| 223 | } |
| 224 | |
| 225 | static struct command_result *json_memleak(struct command *cmd, |
| 226 | const char *buffer, |
| 227 | const jsmntok_t *obj UNNEEDED, |
| 228 | const jsmntok_t *params) |
| 229 | { |
| 230 | struct lightningd *ld = cmd->ld; |
| 231 | struct leak_detect *leaks; |
| 232 | |
| 233 | if (!param_check(cmd, buffer, params, NULL)) |
| 234 | return command_param_failed(); |
| 235 | |
| 236 | if (!getenv("LIGHTNINGD_DEV_MEMLEAK")) { |
| 237 | return command_fail(cmd, LIGHTNINGD, |
| 238 | "Leak detection needs $LIGHTNINGD_DEV_MEMLEAK"); |
| 239 | } |
| 240 | |
| 241 | if (command_check_only(cmd)) |
| 242 | return command_check_done(cmd); |
| 243 | |
| 244 | leaks = tal(cmd, struct leak_detect); |
| 245 | leaks->ld = cmd->ld; |
| 246 | leaks->cmd = cmd; |
| 247 | leaks->num_outstanding_requests = 0; |
| 248 | leaks->leakers = tal_arr(leaks, const char *, 0); |
| 249 | |
| 250 | /* Now do all the async ones. By doing connectd first, it |
| 251 | * has the side-effect of suppressing the complaint it makes |
| 252 | * about us being unresponsive. */ |
| 253 | start_leak_request(subd_req(ld->connectd, ld->connectd, |
| 254 | take(towire_connectd_dev_memleak(NULL)), |
| 255 | -1, 0, connect_dev_memleak_done, leaks), |
| 256 | leaks); |
| 257 | start_leak_request(subd_req(ld->gossip, ld->gossip, |
| 258 | take(towire_gossipd_dev_memleak(NULL)), |
| 259 | -1, 0, gossip_dev_memleak_done, leaks), |
| 260 | leaks); |
| 261 | |
| 262 | /* Ask all per-peer daemons */ |
| 263 | peer_dev_memleak(ld, leaks); |
| 264 | |
| 265 | /* Set timer: dualopend doesn't always listen! */ |
| 266 | notleak(new_reltimer(ld->timers, leaks, time_from_sec(20), |
| 267 | leak_detect_timeout, leaks)); |
| 268 | return command_still_pending(cmd); |
| 269 | } |
| 270 | |
| 271 | static const struct json_command dev_memleak_command = { |
| 272 | "dev-memleak", |
nothing calls this directly
no test coverage detected