askrene: make "child.c" to be the explicit child entry point.
The fork logic itself is pretty simple, so do that directly in askrene.c, and then call into "run_child()" almost as soon as we do the fork. Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
This commit is contained in:
@@ -2,10 +2,10 @@ PLUGIN_ASKRENE_PARENT_SRC := \
|
||||
plugins/askrene/askrene.c \
|
||||
plugins/askrene/datastore_wire.c \
|
||||
plugins/askrene/layer.c \
|
||||
plugins/askrene/reserve.c \
|
||||
plugins/askrene/reserve.c
|
||||
|
||||
PLUGIN_ASKRENE_CHILD_SRC := \
|
||||
plugins/askrene/child/entry.c \
|
||||
plugins/askrene/child/child.c \
|
||||
plugins/askrene/child/mcf.c \
|
||||
plugins/askrene/child/dijkstra.c \
|
||||
plugins/askrene/child/flow.c \
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
*/
|
||||
#include "config.h"
|
||||
#include <ccan/array_size/array_size.h>
|
||||
#include <ccan/noerr/noerr.h>
|
||||
#include <ccan/tal/grab_file/grab_file.h>
|
||||
#include <ccan/tal/str/str.h>
|
||||
#include <common/clock_time.h>
|
||||
@@ -24,7 +25,8 @@
|
||||
#include <math.h>
|
||||
#include <plugins/askrene/askrene.h>
|
||||
#include <plugins/askrene/child/additional_costs.h>
|
||||
#include <plugins/askrene/child/entry.h>
|
||||
#include <plugins/askrene/child/child.h>
|
||||
#include <plugins/askrene/child/child_log.h>
|
||||
#include <plugins/askrene/layer.h>
|
||||
#include <plugins/askrene/reserve.h>
|
||||
#include <sys/wait.h>
|
||||
@@ -522,12 +524,11 @@ static struct command_result *do_getroutes(struct command *cmd,
|
||||
bool include_fees;
|
||||
const char *err;
|
||||
struct timemono deadline;
|
||||
int child_fd, log_fd;
|
||||
int replyfds[2], logfds[2];
|
||||
struct router_child *child;
|
||||
const struct layer **layers;
|
||||
s8 *biases;
|
||||
fp16_t *capacities;
|
||||
int ecode;
|
||||
|
||||
/* update the gossmap */
|
||||
if (gossmap_refresh(askrene->gossmap)) {
|
||||
@@ -625,31 +626,56 @@ static struct command_result *do_getroutes(struct command *cmd,
|
||||
child->start = time_mono();
|
||||
deadline = timemono_add(child->start,
|
||||
time_from_sec(askrene->route_seconds));
|
||||
child_fd = fork_router_child(askrene->gossmap,
|
||||
layers,
|
||||
biases,
|
||||
info->additional_costs,
|
||||
askrene->reserved,
|
||||
take(capacities),
|
||||
info->dev_algo == ALGO_SINGLE_PATH,
|
||||
deadline, srcnode, dstnode, info->amount,
|
||||
info->maxfee, info->finalcltv, info->maxdelay, info->maxparts,
|
||||
include_fees,
|
||||
cmd->id, cmd->filter, &log_fd, &child->pid);
|
||||
/* Save this, as remove_localmods won't preserve it. */
|
||||
ecode = errno;
|
||||
/* We don't need this any more. */
|
||||
gossmap_remove_localmods(askrene->gossmap, localmods);
|
||||
|
||||
if (child_fd == -1) {
|
||||
err = tal_fmt(tmpctx, "failed to fork: %s", strerror(ecode));
|
||||
gossmap_remove_localmods(askrene->gossmap, localmods);
|
||||
if (pipe(replyfds) != 0) {
|
||||
err = tal_fmt(tmpctx, "failed to create pipes: %s", strerror(errno));
|
||||
goto fail_broken;
|
||||
}
|
||||
if (pipe(logfds) != 0) {
|
||||
err = tal_fmt(tmpctx, "failed to create pipes: %s", strerror(errno));
|
||||
close_noerr(replyfds[0]);
|
||||
close_noerr(replyfds[1]);
|
||||
goto fail_broken;
|
||||
}
|
||||
child->pid = fork();
|
||||
if (child->pid < 0) {
|
||||
err = tal_fmt(tmpctx, "failed to fork: %s", strerror(errno));
|
||||
close_noerr(replyfds[0]);
|
||||
close_noerr(replyfds[1]);
|
||||
close_noerr(logfds[0]);
|
||||
close_noerr(logfds[1]);
|
||||
goto fail_broken;
|
||||
}
|
||||
|
||||
child->reply_conn = io_new_conn(child, child_fd,
|
||||
if (child->pid == 0) {
|
||||
/* We are the child. Run the algo */
|
||||
close(logfds[0]);
|
||||
close(replyfds[0]);
|
||||
set_child_log_fd(logfds[1]);
|
||||
|
||||
/* Does not return! */
|
||||
run_child(askrene->gossmap,
|
||||
layers,
|
||||
biases,
|
||||
info->additional_costs,
|
||||
askrene->reserved,
|
||||
take(capacities),
|
||||
info->dev_algo == ALGO_SINGLE_PATH,
|
||||
deadline, srcnode, dstnode, info->amount,
|
||||
info->maxfee, info->finalcltv, info->maxdelay, info->maxparts,
|
||||
include_fees,
|
||||
cmd->id, cmd->filter, replyfds[1]);
|
||||
abort();
|
||||
}
|
||||
|
||||
close(logfds[1]);
|
||||
close(replyfds[1]);
|
||||
|
||||
/* We don't need this any more. */
|
||||
gossmap_remove_localmods(askrene->gossmap, localmods);
|
||||
child->reply_conn = io_new_conn(child, replyfds[0],
|
||||
child_reply_init, child);
|
||||
child->log_conn = io_new_conn(child, log_fd, child_log_init, child);
|
||||
child->log_conn = io_new_conn(child, logfds[0], child_log_init, child);
|
||||
child->cmd = cmd;
|
||||
|
||||
list_add_tail(&askrene->children, &child->list);
|
||||
|
||||
@@ -1,18 +1,16 @@
|
||||
#include "config.h"
|
||||
#include <assert.h>
|
||||
#include <ccan/json_out/json_out.h>
|
||||
#include <ccan/noerr/noerr.h>
|
||||
#include <ccan/read_write_all/read_write_all.h>
|
||||
#include <ccan/tal/str/str.h>
|
||||
#include <common/json_stream.h>
|
||||
#include <common/route.h>
|
||||
#include <common/utils.h>
|
||||
#include <plugins/askrene/child/child.h>
|
||||
#include <plugins/askrene/child/child_log.h>
|
||||
#include <plugins/askrene/child/entry.h>
|
||||
#include <plugins/askrene/child/flow.h>
|
||||
#include <plugins/askrene/child/mcf.h>
|
||||
#include <plugins/askrene/child/route_query.h>
|
||||
#include <unistd.h>
|
||||
|
||||
/* A single route. */
|
||||
struct route {
|
||||
@@ -195,26 +193,23 @@ static struct route_query *new_route_query(const tal_t *ctx,
|
||||
return rq;
|
||||
}
|
||||
|
||||
/* Returns fd to child */
|
||||
int fork_router_child(const struct gossmap *gossmap,
|
||||
const struct layer **layers,
|
||||
const s8 *biases,
|
||||
const struct additional_cost_htable *additional_costs,
|
||||
struct reserve_htable *reserved,
|
||||
fp16_t *capacities TAKES,
|
||||
bool single_path,
|
||||
struct timemono deadline,
|
||||
const struct gossmap_node *srcnode,
|
||||
const struct gossmap_node *dstnode,
|
||||
struct amount_msat amount, struct amount_msat maxfee,
|
||||
u32 finalcltv, u32 maxdelay, size_t maxparts,
|
||||
bool include_fees,
|
||||
const char *cmd_id,
|
||||
struct json_filter *cmd_filter,
|
||||
int *log_fd,
|
||||
int *child_pid)
|
||||
void run_child(const struct gossmap *gossmap,
|
||||
const struct layer **layers,
|
||||
const s8 *biases,
|
||||
const struct additional_cost_htable *additional_costs,
|
||||
struct reserve_htable *reserved,
|
||||
fp16_t *capacities TAKES,
|
||||
bool single_path,
|
||||
struct timemono deadline,
|
||||
const struct gossmap_node *srcnode,
|
||||
const struct gossmap_node *dstnode,
|
||||
struct amount_msat amount, struct amount_msat maxfee,
|
||||
u32 finalcltv, u32 maxdelay, size_t maxparts,
|
||||
bool include_fees,
|
||||
const char *cmd_id,
|
||||
struct json_filter *cmd_filter,
|
||||
int replyfd)
|
||||
{
|
||||
int replyfds[2], logfds[2];
|
||||
double probability;
|
||||
struct flow **flows;
|
||||
struct route **routes;
|
||||
@@ -223,35 +218,6 @@ int fork_router_child(const struct gossmap *gossmap,
|
||||
size_t len;
|
||||
struct route_query *rq;
|
||||
|
||||
if (pipe(replyfds) != 0)
|
||||
goto parent_fail;
|
||||
if (pipe(logfds) != 0) {
|
||||
close_noerr(replyfds[0]);
|
||||
close_noerr(replyfds[1]);
|
||||
goto parent_fail;
|
||||
}
|
||||
*child_pid = fork();
|
||||
if (*child_pid < 0) {
|
||||
close_noerr(replyfds[0]);
|
||||
close_noerr(replyfds[1]);
|
||||
close_noerr(logfds[0]);
|
||||
close_noerr(logfds[1]);
|
||||
goto parent_fail;
|
||||
}
|
||||
if (*child_pid != 0) {
|
||||
close(logfds[1]);
|
||||
close(replyfds[1]);
|
||||
*log_fd = logfds[0];
|
||||
if (taken(capacities))
|
||||
tal_free(capacities);
|
||||
return replyfds[0];
|
||||
}
|
||||
|
||||
/* We are the child. Run the algo */
|
||||
close(logfds[0]);
|
||||
close(replyfds[0]);
|
||||
set_child_log_fd(logfds[1]);
|
||||
|
||||
/* We exit below, so we don't bother freeing this */
|
||||
rq = new_route_query(NULL, gossmap, cmd_id, layers,
|
||||
biases, additional_costs,
|
||||
@@ -266,7 +232,7 @@ int fork_router_child(const struct gossmap *gossmap,
|
||||
maxparts, &flows, &probability);
|
||||
}
|
||||
if (err) {
|
||||
write_all(replyfds[1], err, strlen(err));
|
||||
write_all(replyfd, err, strlen(err));
|
||||
/* Non-zero exit tells parent this is an error string. */
|
||||
exit(1);
|
||||
}
|
||||
@@ -305,13 +271,8 @@ int fork_router_child(const struct gossmap *gossmap,
|
||||
json_stream_close(js, NULL);
|
||||
|
||||
p = json_out_contents(js->jout, &len);
|
||||
if (!write_all(replyfds[1], p, len))
|
||||
if (!write_all(replyfd, p, len))
|
||||
abort();
|
||||
exit(0);
|
||||
|
||||
parent_fail:
|
||||
if (taken(capacities))
|
||||
tal_free(capacities);
|
||||
return -1;
|
||||
}
|
||||
|
||||
36
plugins/askrene/child/child.h
Normal file
36
plugins/askrene/child/child.h
Normal file
@@ -0,0 +1,36 @@
|
||||
#ifndef LIGHTNING_PLUGINS_ASKRENE_CHILD_CHILD_H
|
||||
#define LIGHTNING_PLUGINS_ASKRENE_CHILD_CHILD_H
|
||||
#include "config.h"
|
||||
#include <ccan/compiler/compiler.h>
|
||||
#include <ccan/short_types/short_types.h>
|
||||
#include <ccan/time/time.h>
|
||||
#include <common/amount.h>
|
||||
#include <common/fp16.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
struct additional_cost_htable;
|
||||
struct gossmap;
|
||||
struct json_filter;
|
||||
struct layer;
|
||||
struct reserve_htable;
|
||||
|
||||
/* This is the child. Do the thing. */
|
||||
void run_child(const struct gossmap *gossmap,
|
||||
const struct layer **layers,
|
||||
const s8 *biases,
|
||||
const struct additional_cost_htable *additional_costs,
|
||||
struct reserve_htable *reserved,
|
||||
fp16_t *capacities TAKES,
|
||||
bool single_path,
|
||||
struct timemono deadline,
|
||||
const struct gossmap_node *srcnode,
|
||||
const struct gossmap_node *dstnode,
|
||||
struct amount_msat amount, struct amount_msat maxfee,
|
||||
u32 finalcltv, u32 maxdelay, size_t maxparts,
|
||||
bool include_fees,
|
||||
const char *cmd_id,
|
||||
struct json_filter *cmd_filter,
|
||||
int reply_fd) NORETURN;
|
||||
|
||||
#endif /* LIGHTNING_PLUGINS_ASKRENE_CHILD_CHILD_H */
|
||||
|
||||
@@ -1,35 +0,0 @@
|
||||
#ifndef LIGHTNING_PLUGINS_ASKRENE_CHILD_ENTRY_H
|
||||
#define LIGHTNING_PLUGINS_ASKRENE_CHILD_ENTRY_H
|
||||
#include "config.h"
|
||||
#include <ccan/short_types/short_types.h>
|
||||
#include <ccan/time/time.h>
|
||||
#include <common/amount.h>
|
||||
#include <common/fp16.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
struct route_query;
|
||||
struct gossmap_node;
|
||||
struct json_filter;
|
||||
struct layer;
|
||||
struct reserve_htable;
|
||||
struct additional_cost_htable;
|
||||
|
||||
/* Entry point to the child process. */
|
||||
int fork_router_child(const struct gossmap *gossmap,
|
||||
const struct layer **layers,
|
||||
const s8 *biases,
|
||||
const struct additional_cost_htable *additional_costs,
|
||||
struct reserve_htable *reserved,
|
||||
fp16_t *capacities TAKES,
|
||||
bool single_path,
|
||||
struct timemono deadline,
|
||||
const struct gossmap_node *srcnode,
|
||||
const struct gossmap_node *dstnode,
|
||||
struct amount_msat amount, struct amount_msat maxfee,
|
||||
u32 finalcltv, u32 maxdelay, size_t maxparts,
|
||||
bool include_fees,
|
||||
const char *cmd_id,
|
||||
struct json_filter *cmd_filter,
|
||||
int *log_fd,
|
||||
int *child_pid);
|
||||
#endif /* LIGHTNING_PLUGINS_ASKRENE_CHILD_ENTRY_H */
|
||||
Reference in New Issue
Block a user