summary |
shortlog |
log |
commit | commitdiff |
tree
raw |
patch |
inline | side by side (from parent 1:
7582953)
Introduce a new variable st->resolving which tracks whether we have an
outstanding name resolution request. This makes it safe to (try to)
start name resolution (via the new function ensure_resolving) multiple
times etc.
No resulting functional change from just this patch.
Signed-off-by: Ian Jackson <ijackson@chiark.greenend.org.uk>
---
Changes in v2:
* Do slightly complicated dance with st->resolving, which is needed
because of the reentrancy hazard posted by resolver->request. In
v1 of the series there was a bug here which could cause the site
state machine to lock up.
uint32_t state;
uint64_t now; /* Most recently seen time */
bool_t allow_send_prod;
uint32_t state;
uint64_t now; /* Most recently seen time */
bool_t allow_send_prod;
/* The currently established session */
struct data_key current;
/* The currently established session */
struct data_key current;
struct site *st=sst;
struct comm_addr ca_buf, *ca_use;
struct site *st=sst;
struct comm_addr ca_buf, *ca_use;
if (st->state!=SITE_RESOLVE) {
slog(st,LOG_UNEXPECTED,"site_resolve_callback called unexpectedly");
return;
if (st->state!=SITE_RESOLVE) {
slog(st,LOG_UNEXPECTED,"site_resolve_callback called unexpectedly");
return;
+static bool_t ensure_resolving(struct site *st)
+{
+ /* Reentrancy hazard: may call site_resolve_callback and hence
+ * enter_new_state, enter_state_* and generate_msg*. */
+ if (st->resolving)
+ return True;
+
+ /* resolver->request might reentrantly call site_resolve_callback
+ * which will clear st->resolving, so we need to set it beforehand
+ * rather than afterwards; also, it might return False, in which
+ * case we have to clear ->resolving again. */
+ st->resolving=True;
+ bool_t ok = st->resolver->request(st->resolver->st,st->address,
+ site_resolve_callback,st);
+ if (!ok)
+ st->resolving=False;
+
+ return ok;
+}
+
static bool_t enter_state_resolve(struct site *st)
{
/* Reentrancy hazard! See ensure_resolving. */
state_assert(st,st->state==SITE_RUN);
slog(st,LOG_STATE,"entering state RESOLVE");
st->state=SITE_RESOLVE;
static bool_t enter_state_resolve(struct site *st)
{
/* Reentrancy hazard! See ensure_resolving. */
state_assert(st,st->state==SITE_RUN);
slog(st,LOG_STATE,"entering state RESOLVE");
st->state=SITE_RESOLVE;
- return st->resolver->request(st->resolver->st,st->address,
- site_resolve_callback,st);
+ return ensure_resolving(st);
}
static bool_t enter_new_state(struct site *st, uint32_t next)
}
static bool_t enter_new_state(struct site *st, uint32_t next)
st->log_events=string_list_to_word(dict_lookup(dict,"log-events"),
log_event_table,"site");
st->log_events=string_list_to_word(dict_lookup(dict,"log-events"),
log_event_table,"site");
st->allow_send_prod=0;
st->tunname=safe_malloc(strlen(st->localname)+strlen(st->remotename)+5,
st->allow_send_prod=0;
st->tunname=safe_malloc(strlen(st->localname)+strlen(st->remotename)+5,