Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make sure other tasks are processed with tasklists that contain both bad xfrs (that cause reload to exit) and other tasks #332

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 7 additions & 10 deletions difffile.c
Original file line number Diff line number Diff line change
Expand Up @@ -1276,8 +1276,7 @@ check_for_bad_serial(namedb_type* db, const char* zone_str, uint32_t old_serial)

int
apply_ixfr_for_zone(nsd_type* nsd, zone_type* zone, FILE* in,
struct nsd_options* ATTR_UNUSED(opt), udb_base* taskudb, udb_ptr* last_task,
uint32_t xfrfilenr)
struct nsd_options* ATTR_UNUSED(opt), udb_base* taskudb, uint32_t xfrfilenr)
{
char zone_buf[3072];
char log_buf[5120];
Expand All @@ -1289,7 +1288,6 @@ apply_ixfr_for_zone(nsd_type* nsd, zone_type* zone, FILE* in,
uint8_t committed;
uint32_t i;
int num_bytes = 0;
(void)last_task;
assert(zone);

/* read zone name and serial */
Expand Down Expand Up @@ -2085,9 +2083,8 @@ task_process_zonestat_inc(struct nsd* nsd, udb_base* udb, udb_ptr *last_task,
}
#endif

static void
task_process_apply_xfr(struct nsd* nsd, udb_base* udb, udb_ptr *last_task,
udb_ptr* task)
void
task_process_apply_xfr(struct nsd* nsd, udb_base* udb, udb_ptr* task)
{
/* we have to use an udb_ptr task here, because the apply_xfr procedure
* appends soa_info which may remap and change the pointer. */
Expand All @@ -2099,6 +2096,7 @@ task_process_apply_xfr(struct nsd* nsd, udb_base* udb, udb_ptr *last_task,
if(!zone) {
/* assume the zone has been deleted and a zone transfer was
* still waiting to be processed */
udb_ptr_free_space(task, udb, TASKLIST(task)->size);
return;
}

Expand All @@ -2110,10 +2108,11 @@ task_process_apply_xfr(struct nsd* nsd, udb_base* udb, udb_ptr *last_task,
/* soainfo_gone will be communicated from server_reload, unless
preceding updates have been applied */
zone->is_skipped = 1;
udb_ptr_free_space(task, udb, TASKLIST(task)->size);
return;
}
/* read and apply zone transfer */
switch(apply_ixfr_for_zone(nsd, zone, df, nsd->options, udb, last_task,
switch(apply_ixfr_for_zone(nsd, zone, df, nsd->options, udb,
TASKLIST(task)->yesno)) {
case 1: /* Success */
break;
Expand All @@ -2131,6 +2130,7 @@ task_process_apply_xfr(struct nsd* nsd, udb_base* udb, udb_ptr *last_task,
default:break;
}
fclose(df);
udb_ptr_free_space(task, udb, TASKLIST(task)->size);
}


Expand Down Expand Up @@ -2176,9 +2176,6 @@ void task_process_in_reload(struct nsd* nsd, udb_base* udb, udb_ptr *last_task,
task_process_zonestat_inc(nsd, udb, last_task, TASKLIST(task));
break;
#endif
case task_apply_xfr:
task_process_apply_xfr(nsd, udb, last_task, task);
break;
case task_add_cookie_secret:
task_process_add_cookie_secret(nsd, TASKLIST(task));
break;
Expand Down
4 changes: 2 additions & 2 deletions difffile.h
Original file line number Diff line number Diff line change
Expand Up @@ -68,8 +68,7 @@ int add_RR(namedb_type* db, const dname_type* dname,

/* apply the xfr file identified by xfrfilenr to zone */
int apply_ixfr_for_zone(struct nsd* nsd, zone_type* zone, FILE* in,
struct nsd_options* opt, udb_base* taskudb, udb_ptr* last_task,
uint32_t xfrfilenr);
struct nsd_options* opt, udb_base* taskudb, uint32_t xfrfilenr);

enum soainfo_hint {
soainfo_ok,
Expand Down Expand Up @@ -157,6 +156,7 @@ void task_new_drop_cookie_secret(udb_base* udb, udb_ptr* last);
void task_new_activate_cookie_secret(udb_base* udb, udb_ptr* last);
int task_new_apply_xfr(udb_base* udb, udb_ptr* last, const dname_type* zone,
uint32_t old_serial, uint32_t new_serial, uint64_t filenumber);
void task_process_apply_xfr(struct nsd* nsd, udb_base* udb, udb_ptr *task);
void task_process_in_reload(struct nsd* nsd, udb_base* udb, udb_ptr *last_task,
udb_ptr* task);
void task_process_expire(namedb_type* db, struct task_list_d* task);
Expand Down
162 changes: 111 additions & 51 deletions server.c
Original file line number Diff line number Diff line change
Expand Up @@ -2264,47 +2264,81 @@ block_read(struct nsd* nsd, int s, void* p, ssize_t sz, int timeout)
}

static void
reload_process_tasks(struct nsd* nsd, udb_ptr* last_task, int cmdsocket)
reload_process_non_xfr_tasks(struct nsd* nsd, udb_ptr* xfrs2process,
udb_ptr* last_task)
{
sig_atomic_t cmd = NSD_QUIT_SYNC;
udb_ptr t, next;
udb_ptr t, next, xfr_tail;
udb_base* u = nsd->task[nsd->mytask];
udb_ptr_init(&next, u);
udb_ptr_init(&xfr_tail, u);
udb_ptr_new(&t, u, udb_base_get_userdata(u));
udb_base_set_userdata(u, 0);
/* Execute all tasks except of type "task_apply_xfr". */
while(!udb_ptr_is_null(&t)) {
/* store next in list so this one can be deleted or reused */
udb_ptr_set_rptr(&next, u, &TASKLIST(&t)->next);
udb_rptr_zero(&TASKLIST(&t)->next, u);

/* process task t */
/* append results for task t and update last_task */
task_process_in_reload(nsd, u, last_task, &t);
if(TASKLIST(&t)->task_type != task_apply_xfr) {
/* process task t */
/* append results for task t and update last_task */
task_process_in_reload(nsd, u, last_task, &t);

} else if(udb_ptr_is_null(xfrs2process)) {
udb_ptr_set_ptr( xfrs2process, u, &t);
udb_ptr_set_ptr(&xfr_tail, u, &t);
} else {
udb_rptr_set_ptr(&TASKLIST(&xfr_tail)->next, u, &t);
udb_ptr_set_ptr(&xfr_tail, u, &t);
}
/* go to next */
udb_ptr_set_ptr(&t, u, &next);
}
/* t and next are already unlinked (because they are null) */
udb_ptr_unlink(&xfr_tail, u);
}

/* if the parent has quit, we must quit too, poll the fd for cmds */
if(block_read(nsd, cmdsocket, &cmd, sizeof(cmd), 0) == sizeof(cmd)) {
DEBUG(DEBUG_IPC,1, (LOG_INFO, "reload: ipc command from main %d", (int)cmd));
if(cmd == NSD_QUIT) {
DEBUG(DEBUG_IPC,1, (LOG_INFO, "reload: quit to follow nsd"));
/* unlink files of remainder of tasks */
while(!udb_ptr_is_null(&t)) {
if(TASKLIST(&t)->task_type == task_apply_xfr) {
xfrd_unlink_xfrfile(nsd, TASKLIST(&t)->yesno);
}
udb_ptr_set_rptr(&t, u, &TASKLIST(&t)->next);
}
udb_ptr_unlink(&t, u);
udb_ptr_unlink(&next, u);
exit(0);
static size_t
reload_process_xfr_tasks(struct nsd* nsd, int cmdsocket, udb_ptr* xfrs2process)
{
sig_atomic_t cmd = NSD_QUIT_SYNC;
udb_ptr next;
udb_base* u = nsd->task[nsd->mytask];
size_t xfrs_processed = 0;

udb_ptr_init(&next, u);
while(!udb_ptr_is_null(xfrs2process)) {
/* store next in list so this one can be deleted or reused */
udb_ptr_set_rptr(&next, u, &TASKLIST(xfrs2process)->next);
udb_rptr_zero(&TASKLIST(xfrs2process)->next, u);

/* process xfr task at xfrs2process */
assert(TASKLIST(xfrs2process)->task_type == task_apply_xfr);
task_process_apply_xfr(nsd, u, xfrs2process);
xfrs_processed += 1;

/* go to next */
udb_ptr_set_ptr(xfrs2process, u, &next);

/* if the "old-main" has quit, we must quit too, poll the fd for cmds */
if(block_read(nsd, cmdsocket, &cmd, sizeof(cmd), 0) != sizeof(cmd))
; /* pass */
else if (cmd != NSD_QUIT)
DEBUG(DEBUG_IPC,1, (LOG_INFO, "reload: ipc command from old-main %d", (int)cmd));
else {
udb_ptr_unlink(&next, u);
DEBUG(DEBUG_IPC,1, (LOG_INFO, "reload: quit to follow nsd"));
/* unlink files of remainder of tasks */
while(!udb_ptr_is_null(xfrs2process)) {
assert(TASKLIST(xfrs2process)->task_type == task_apply_xfr);
xfrd_unlink_xfrfile(nsd, TASKLIST(xfrs2process)->yesno);
udb_ptr_set_rptr(xfrs2process, u, &TASKLIST(xfrs2process)->next);
}
exit(0);
}

}
udb_ptr_unlink(&t, u);
udb_ptr_unlink(&next, u);
/* xfrs2process and next are already unlinked (because they are null) */
return xfrs_processed;
}

static void server_verify(struct nsd *nsd, int cmdsocket,
Expand Down Expand Up @@ -2388,18 +2422,18 @@ static void server_reload_handle_quit_sync_ack(int cmdsocket, short event,
*/
static void
server_reload(struct nsd *nsd, region_type* server_region, netio_type* netio,
int cmdsocket)
int cmdsocket, udb_ptr* xfrs2process, udb_ptr* last_task)
{
pid_t mypid;
sig_atomic_t cmd;
udb_ptr last_task;
struct sigaction old_sigchld, ign_sigchld;
struct radnode* node;
zone_type* zone;
enum soainfo_hint hint;
struct quit_sync_event_data cb_data;
struct event signal_event, cmd_event;
struct timeval reload_sync_timeout;
size_t xfrs_processed = 0;

/* ignore SIGCHLD from the previous server_main that used this pid */
memset(&ign_sigchld, 0, sizeof(ign_sigchld));
Expand All @@ -2413,9 +2447,7 @@ server_reload(struct nsd *nsd, region_type* server_region, netio_type* netio,
#endif

/* see what tasks we got from xfrd */
task_remap(nsd->task[nsd->mytask]);
udb_ptr_init(&last_task, nsd->task[nsd->mytask]);
reload_process_tasks(nsd, &last_task, cmdsocket);
xfrs_processed = reload_process_xfr_tasks(nsd, cmdsocket, xfrs2process);

#ifndef NDEBUG
if(nsd_debug_level >= 1)
Expand Down Expand Up @@ -2452,10 +2484,9 @@ server_reload(struct nsd *nsd, region_type* server_region, netio_type* netio,
#endif
}

for(node = radix_first(nsd->db->zonetree);
node != NULL;
node = radix_next(node))
{
if(xfrs_processed) for( node = radix_first(nsd->db->zonetree)
; node != NULL; node = radix_next(node)) {

zone = (zone_type *)node->elem;
if(zone->is_updated) {
if(zone->is_bad) {
Expand All @@ -2467,12 +2498,12 @@ server_reload(struct nsd *nsd, region_type* server_region, netio_type* netio,
/* update(s), verified or not, possibly with subsequent
skipped update(s). skipped update(s) are picked up
by failed update check in xfrd */
task_new_soainfo(nsd->task[nsd->mytask], &last_task,
task_new_soainfo(nsd->task[nsd->mytask], last_task,
zone, hint);
} else if(zone->is_skipped) {
/* corrupt or inconsistent update without preceding
update(s), communicate soainfo_gone */
task_new_soainfo(nsd->task[nsd->mytask], &last_task,
task_new_soainfo(nsd->task[nsd->mytask], last_task,
zone, soainfo_gone);
}
zone->is_updated = 0;
Expand Down Expand Up @@ -2565,7 +2596,7 @@ server_reload(struct nsd *nsd, region_type* server_region, netio_type* netio,
exit(1);
}
assert(cmd == NSD_RELOAD);
udb_ptr_unlink(&last_task, nsd->task[nsd->mytask]);
udb_ptr_unlink(last_task, nsd->task[nsd->mytask]);
task_process_sync(nsd->task[nsd->mytask]);
#ifdef USE_ZONE_STATS
server_zonestat_realloc(nsd); /* realloc for next children */
Expand Down Expand Up @@ -2642,6 +2673,10 @@ server_main(struct nsd *nsd)
netio_type *netio = netio_create(server_region);
netio_handler_type reload_listener;
int reload_sockets[2] = {-1, -1};
/* pointer to the xfr tasks that will be processed in a second pass */
udb_ptr xfrs2process;
/* pointer to results of task processing */
udb_ptr last_task;
struct timespec timeout_spec;
int status;
pid_t child_pid;
Expand All @@ -2659,6 +2694,8 @@ server_main(struct nsd *nsd)
nsd->st->db_disk = 0;
nsd->st->db_mem = region_get_mem(nsd->db->region);
#endif
memset(&xfrs2process, 0, sizeof(xfrs2process));
memset(&last_task, 0, sizeof(last_task));

/* Start the child processes that handle incoming queries */
if (server_start_children(nsd, server_region, netio,
Expand Down Expand Up @@ -2859,7 +2896,22 @@ server_main(struct nsd *nsd)
reload_pid = -1;
break;
}

/* Execute the tasks that cannot fail */
#ifdef HAVE_SETPROCTITLE
setproctitle("load");
#endif
#ifdef USE_LOG_PROCESS_ROLE
log_set_process_role("load");
#endif
/* Already process the non xfr tasks, so that a failed
* transfer (which can exit) will not nullify the
* effects of the other tasks that will not exit.
*/
task_remap(nsd->task[nsd->mytask]);
udb_ptr_init(&xfrs2process, nsd->task[nsd->mytask]);
udb_ptr_init(&last_task , nsd->task[nsd->mytask]);
reload_process_non_xfr_tasks(nsd, &xfrs2process
, &last_task);
/* Do actual reload */
reload_pid = fork();
switch (reload_pid) {
Expand All @@ -2869,21 +2921,11 @@ server_main(struct nsd *nsd)
default:
/* PARENT */
close(reload_sockets[0]);
#ifdef HAVE_SETPROCTITLE
setproctitle("load");
#endif
#ifdef USE_LOG_PROCESS_ROLE
log_set_process_role("load");
#endif
server_reload(nsd, server_region, netio,
reload_sockets[1]);
server_reload(nsd, server_region, netio
, reload_sockets[1]
, &xfrs2process
, &last_task);
DEBUG(DEBUG_IPC,2, (LOG_INFO, "Reload exited to become new main"));
#ifdef HAVE_SETPROCTITLE
setproctitle("main");
#endif
#ifdef USE_LOG_PROCESS_ROLE
log_set_process_role("main");
#endif
close(reload_sockets[1]);
DEBUG(DEBUG_IPC,2, (LOG_INFO, "Reload closed"));
/* drop stale xfrd ipc data */
Expand Down Expand Up @@ -2915,6 +2957,24 @@ server_main(struct nsd *nsd)
reload_pid = getppid();
break;
}
if(reload_pid == -1) {
/* Reset proctitle after "load" process exited
* or when fork() failed
*/
#ifdef HAVE_SETPROCTITLE
setproctitle("main");
#endif
#ifdef USE_LOG_PROCESS_ROLE
log_set_process_role("main");
#endif
}
/* xfrs2process and last_task need to be reset in case
* "old-main" becomes "main" (due to an failed (exited)
* xfr update). If needed xfrs2process gets unlinked by
* "load", and last_task by the xfrd.
*/
memset(&xfrs2process, 0, sizeof(xfrs2process));
memset(&last_task, 0, sizeof(last_task));
break;
case NSD_QUIT_SYNC:
/* synchronisation of xfrd, parent and reload */
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
-----BEGIN PRIVATE KEY-----
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
Lfohlvr92Vv2N1gGcBSyrwTY
-----END PRIVATE KEY-----
Loading