void dnscore_stop_timer() { /* * Timer thread stop */ int mypid = getpid(); if(mypid == dnscore_timer_creator_pid) { smp_int_set(&dnscore_running, 0); if(dnscore_timer_thread_id != 0) { log_debug("stopping timer"); pthread_join(dnscore_timer_thread_id, NULL); pthread_detach(dnscore_timer_thread_id); dnscore_timer_creator_pid = 0; dnscore_timer_thread_id = 0; } } else { #ifndef NDEBUG log_debug("timer owned by %d (0 meaning stopped already), not touching it (I'm %d)", dnscore_timer_creator_pid, mypid); #endif } logger_flush(); }
void log_assert__(bool b, const char *txt, const char *file, int line) { if(!b) { log_err("assert: at %s:%d: %s", file, line, txt); /* this is in zassert */ logger_flush(); sleep(10); /* be nice */ exit(-1); } }
int logger_timer_cb (void *data, int remaining_calls) { /* make C compiler happy */ (void) data; (void) remaining_calls; logger_flush (); return WEECHAT_RC_OK; }
int logger_command_cb (void *data, struct t_gui_buffer *buffer, int argc, char **argv, char **argv_eol) { /* make C compiler happy */ (void) data; (void) argv_eol; if ((argc == 1) || ((argc == 2) && (weechat_strcasecmp (argv[1], "list") == 0))) { logger_list (); return WEECHAT_RC_OK; } if (argc > 1) { if (weechat_strcasecmp (argv[1], "set") == 0) { if (argc > 2) logger_set_buffer (buffer, argv[2]); return WEECHAT_RC_OK; } if (weechat_strcasecmp (argv[1], "flush") == 0) { logger_flush (); return WEECHAT_RC_OK; } if (weechat_strcasecmp (argv[1], "disable") == 0) { logger_set_buffer (buffer, "0"); } } return WEECHAT_RC_OK; }
static void* dnscore_timer_thread(void * unused0) { thread_pool_setup_random_ctx(); int last_call = time(NULL); dnscore_timer_tick = last_call; while(smp_int_get(&dnscore_running) != 0) { /* log & term output flush handling */ stdstream_flush_both_terms(); logger_flush(); /* alarm callback handling */ int period = dnscore_timer_period; do { sleep(period); dnscore_timer_tick = time(NULL); period = dnscore_timer_tick - last_call; } while((period < dnscore_timer_period) && (smp_int_get(&dnscore_running) != 0)); alarm_run_tick(dnscore_timer_tick); last_call = dnscore_timer_tick; } pthread_exit(NULL); return NULL; }
ya_result zdb_icmtl_replay(zdb_zone *zone) { ya_result return_value; u32 serial; zdb_zone_double_lock(zone, ZDB_ZONE_MUTEX_SIMPLEREADER, ZDB_ZONE_MUTEX_LOAD); return_value = zdb_zone_getserial(zone, &serial); // zone is locked if(FAIL(return_value)) { zdb_zone_double_unlock(zone, ZDB_ZONE_MUTEX_SIMPLEREADER, ZDB_ZONE_MUTEX_LOAD); log_err("journal: %{dnsname}: error reading serial for zone: %r", zone->origin, return_value); return return_value; } input_stream is; #if ICMTL_DUMP_JOURNAL_RECORDS log_debug("journal: zdb_icmtl_replay(%{dnsname})", zone->origin); logger_flush(); #endif u32 first_serial; u32 last_serial; if(FAIL(return_value = zdb_zone_journal_get_serial_range(zone, &first_serial, &last_serial))) { zdb_zone_double_unlock(zone, ZDB_ZONE_MUTEX_SIMPLEREADER, ZDB_ZONE_MUTEX_LOAD); if(return_value == ZDB_ERROR_ICMTL_NOTFOUND) { return_value = SUCCESS; } else { log_err("journal: %{dnsname}: error opening journal for zone: %r", zone->origin, return_value); } return return_value; } log_debug("journal: %{dnsname}: zone serial is %i, journal covers serials from %i to %i", zone->origin, serial, first_serial, last_serial); if(last_serial == serial) { zdb_zone_double_unlock(zone, ZDB_ZONE_MUTEX_SIMPLEREADER, ZDB_ZONE_MUTEX_LOAD); log_debug("journal: %{dnsname}: nothing to read from the journal", zone->origin); return 0; } if(serial_lt(serial, first_serial)) { zdb_zone_double_unlock(zone, ZDB_ZONE_MUTEX_SIMPLEREADER, ZDB_ZONE_MUTEX_LOAD); log_warn("journal: %{dnsname}: first serial from the journal is after the zone", zone->origin); // should invalidate the journal zdb_zone_journal_delete(zone); return 0; } if(serial_gt(serial, last_serial)) { zdb_zone_double_unlock(zone, ZDB_ZONE_MUTEX_SIMPLEREADER, ZDB_ZONE_MUTEX_LOAD); log_warn("journal: %{dnsname}: last serial from the journal is before the zone", zone->origin); // should invalidate the journal zdb_zone_journal_delete(zone); return 0; } if(FAIL(return_value = zdb_zone_journal_get_ixfr_stream_at_serial(zone, serial, &is, NULL))) { zdb_zone_double_unlock(zone, ZDB_ZONE_MUTEX_SIMPLEREADER, ZDB_ZONE_MUTEX_LOAD); log_err("journal: %{dnsname}: error reading journal from serial %d: %r",zone->origin, serial, return_value); return return_value; } log_info("journal: %{dnsname}: replaying from serial %u",zone->origin, serial); buffer_input_stream_init(&is, &is, ZDB_ICMTL_REPLAY_BUFFER_SIZE); u16 shutdown_test_countdown = ZDB_ICMTL_REPLAY_SHUTDOWN_POLL_PERIOD; u32 current_serial = serial; /* * Read all records from [ SOA ... SOA ... [ SOA in memory */ output_stream baos; input_stream bais; dns_resource_record rr; int baos_rr_count = 0; int baos_soa_count = 0; bool was_nsec3 = zdb_zone_is_nsec3(zone); bytearray_output_stream_init_ex(&baos, NULL, ZDB_ICMTL_REPLAY_BUFFER_SIZE, BYTEARRAY_DYNAMIC); dns_resource_record_init(&rr); // 0: gather, 1: commit, 2: commit & stop for(int replay_state = ZDB_ICMTL_REPLAY_GATHER; replay_state != ZDB_ICMTL_REPLAY_COMMIT_AND_STOP;) { // ensure it's not supposed to shutdown (every few iterations) if(--shutdown_test_countdown <= 0) { if(dnscore_shuttingdown()) { return_value = STOPPED_BY_APPLICATION_SHUTDOWN; break; } shutdown_test_countdown = ZDB_ICMTL_REPLAY_SHUTDOWN_POLL_PERIOD; } // read the next record if((return_value = dns_resource_record_read(&rr, &is)) <= 0) { if(ISOK(return_value)) { log_info("journal: %{dnsname}: reached the end of the journal file", zone->origin); replay_state = ZDB_ICMTL_REPLAY_COMMIT_AND_STOP; } else { log_err("journal: broken journal: %r", return_value); logger_flush(); // broken journal (flush is slow, but this is bad, so : keep it) replay_state = ZDB_ICMTL_REPLAY_STOP; } } else // first record must be an SOA (or it's wrong) if(baos_rr_count == 0) // first record ? { if(rr.tctr.qtype != TYPE_SOA) // must be SOA { // expected an SOA return_value = ERROR; break; } ++baos_soa_count; // 0 -> 1 // this is not mandatory but clearer to read } else // the page ends with an SOA or end of stream if(rr.tctr.qtype == TYPE_SOA) { if(baos_soa_count == 2) { // this record is the start of the next stream, keep it for the next iteration replay_state = ZDB_ICMTL_REPLAY_COMMIT; } ++baos_soa_count; } ++baos_rr_count; if((replay_state & ZDB_ICMTL_REPLAY_COMMIT) != 0) { log_info("journal: %{dnsname}: committing changes", zone->origin); u64 ts_start = timeus(); zdb_zone_exchange_locks(zone, ZDB_ZONE_MUTEX_SIMPLEREADER, ZDB_ZONE_MUTEX_LOAD); bytearray_input_stream_init_const(&bais, bytearray_output_stream_buffer(&baos), bytearray_output_stream_size(&baos)); return_value = zdb_icmtl_replay_commit(zone, &bais, ¤t_serial); zdb_zone_exchange_locks(zone, ZDB_ZONE_MUTEX_LOAD, ZDB_ZONE_MUTEX_SIMPLEREADER); input_stream_close(&bais); u64 ts_stop = timeus(); if(ts_stop < ts_start) // time change { ts_stop = ts_start; } u64 ts_delta = ts_stop - ts_start; if(ISOK(return_value)) { if(ts_delta < 1000) { log_info("journal: %{dnsname}: committed changes (%lluus)", zone->origin, ts_delta); } else if(ts_delta < 1000000) { double ts_delta_s = ts_delta; ts_delta_s /= 1000.0; log_info("journal: %{dnsname}: committed changes (%5.2fms)", zone->origin, ts_delta_s); } else { double ts_delta_s = ts_delta; ts_delta_s /= 1000000.0; log_info("journal: %{dnsname}: committed changes (%5.2fs)", zone->origin, ts_delta_s); } } else { log_err("journal: %{dnsname}: failed to committed changes", zone->origin); break; } // the current page has been processed if(replay_state == ZDB_ICMTL_REPLAY_COMMIT_AND_STOP) { // no more page to read break; } // reset the state for the next page // note: the next written record will be the last read SOA baos_rr_count = 1; baos_soa_count = 1; replay_state = ZDB_ICMTL_REPLAY_GATHER; bytearray_output_stream_reset(&baos); } // end if replay_state is ZDB_ICMTL_REPLAY_COMMIT (mask) dns_resource_record_write(&rr, &baos); } input_stream_close(&is); output_stream_close(&baos); dns_resource_record_clear(&rr); // cleanup destroyed nsec3 chains if(ISOK(return_value)) { bool is_nsec3 = zdb_zone_is_nsec3(zone); if(is_nsec3 && !was_nsec3) { // the chain has just been created, but is probably missing internal links log_debug("journal: %{dnsname}: zone switched to NSEC3 by reading the journal: updating links", zone->origin); zdb_zone_exchange_locks(zone, ZDB_ZONE_MUTEX_SIMPLEREADER, ZDB_ZONE_MUTEX_LOAD); nsec3_zone_update_chain0_links(zone); zdb_zone_exchange_locks(zone, ZDB_ZONE_MUTEX_LOAD, ZDB_ZONE_MUTEX_SIMPLEREADER); log_debug("journal: %{dnsname}: zone switched to NSEC3 by reading the journal: links updated", zone->origin); } if(FAIL(return_value = zdb_zone_getserial(zone, &serial))) // zone is locked { zdb_zone_double_unlock(zone, ZDB_ZONE_MUTEX_SIMPLEREADER, ZDB_ZONE_MUTEX_LOAD); log_err("journal: %{dnsname}: error reading confirmation serial for zone: %r",zone->origin, return_value); return return_value; } if(serial != last_serial) { log_warn("journal: %{dnsname}: expected serial to be %i but it is %i instead",zone->origin, last_serial, serial); } #if 0 // ICMTL_DUMP_JOURNAL_RECORDS if(is_nsec) { nsec_logdump_tree(zone); logger_flush(); } #endif } zdb_zone_double_unlock(zone, ZDB_ZONE_MUTEX_SIMPLEREADER, ZDB_ZONE_MUTEX_LOAD); log_info("journal: %{dnsname}: done", zone->origin); return return_value; }
ya_result zdb_icmtl_replay_commit(zdb_zone *zone, input_stream *is, u32 *current_serialp) { ya_result ret; /* * 0: DELETE, 1: ADD * The mode is switched every time an SOA is found. */ yassert(zdb_zone_islocked(zone)); #if ZDB_HAS_NSEC3_SUPPORT bool has_nsec3 = zdb_zone_is_nsec3(zone); #endif #if ZDB_HAS_NSEC_SUPPORT bool has_nsec = zdb_zone_is_nsec(zone); #endif #if ZDB_HAS_NSEC3_SUPPORT && ZDB_HAS_NSEC_SUPPORT if(has_nsec3 && has_nsec) { log_err("journal: %{dnsname}: zone has both NSEC and NSEC3 status, which is not supported by YADIFA", zone->origin); return ERROR; } #endif u8 mode = 1; // the first SOA will switch the mode to delete s32 changes = 0; zdb_ttlrdata ttlrdata; dns_resource_record rr; dns_resource_record_init(&rr); const u8 *fqdn = rr.name; dnslabel_vector labels; ttlrdata.next = NULL; /* * The plan for NSEC3 : * Store the fqdn + type class ttl rdata in collections * => the delete collection * => the add collection * Then there is the NSEC3 covered labels: keep a reference to them for later * * When a pass of SOA-/SOA+ has finished: * _ replace the NSEC3 in both collections (reading from delete) * _ delete NSEC3 to delete * _ add NSEC3 to add * * _ and finally update the NSEC3 for the labels kept above */ #if ZDB_HAS_NSEC3_SUPPORT chain_replay nsec3replay; nsec3_chain_replay_init(&nsec3replay, zone); #endif #if ZDB_HAS_NSEC_SUPPORT chain_replay nsecreplay; nsec_chain_replay_init(&nsecreplay, zone); #endif #if ZDB_HAS_NSEC3_SUPPORT ptr_set downed_fqdn = PTR_SET_DNSNAME_EMPTY; #endif /* * At this point : the next record, if it exists AND is not an SOA , has to be deleted * */ bool did_remove_soa = FALSE; // something has to be committed for(;;) { /* * read the full record * * == 0 : no record (EOF) * < 0 : failed */ if((ret = dns_resource_record_read(&rr, is)) <= 0) { if(ISOK(ret)) { log_info("journal: %{dnsname}: reached the end of the journal page", zone->origin); } else { log_err("journal: %{dnsname}: broken journal: %r", zone->origin, ret); logger_flush(); // broken journal (bad, keep me) } break; } ttlrdata.ttl = ntohl(rr.tctr.ttl); ttlrdata.rdata_pointer = rr.rdata; ttlrdata.rdata_size = rr.rdata_size; /* * Stop at the SOA */ if(rr.tctr.qtype == TYPE_SOA) { mode ^= 1; if(mode == 0) { /* ADD */ #if ZDB_HAS_NSEC3_SUPPORT // NSEC3 { ret = nsec3replay.vtbl->execute(&nsec3replay); if(FAIL(ret)) { dns_resource_record_clear(&rr); // DO NOT: input_stream_close(is); nsec3replay.vtbl->finalise(&nsec3replay); #if ZDB_HAS_NSEC_SUPPORT nsecreplay.vtbl->finalise(&nsecreplay); #endif // ZDB_HAS_NSEC_SUPPORT return ret; } } #endif #if ZDB_HAS_NSEC_SUPPORT // NSEC ret = nsecreplay.vtbl->execute(&nsecreplay); #endif //ZDB_HAS_NSEC_SUPPORT } } if(!did_remove_soa) { log_info("journal: %{dnsname}: removing obsolete SOA", zone->origin); if(FAIL(ret = zdb_record_delete(&zone->apex->resource_record_set, TYPE_SOA))) { /** * complain */ log_err("journal: %{dnsname}: removing current SOA gave an error: %r", zone->origin, ret); /* That's VERY bad ... */ changes = ret; break; } did_remove_soa = TRUE; } s32 top = dnsname_to_dnslabel_vector(fqdn, labels); if(mode == 0) { /* * "TO DEL" record */ #if ICMTL_DUMP_JOURNAL_RECORDS rdata_desc type_len_rdata = {rr.tctr.qtype, rr.rdata_size, rr.rdata }; log_debug("journal: del %{dnsname} %{typerdatadesc}", fqdn, &type_len_rdata); logger_flush(); #endif bool added_in_chain = FALSE; #if ZDB_HAS_NSEC3_SUPPORT // 0 : proceed // 1 : ignore // ? : error if((added_in_chain = (nsec3replay.vtbl->record_del(&nsec3replay, fqdn, rr.tctr.qtype, &ttlrdata) != 0))) { // add everything up until a non-empty terminal is found (the apex will thus be automatically avoided) // if the record is a delegation, add everything down too /* if((top > zone->origin_vector.size) && (rr.tctr.qtype != TYPE_NSEC3) && ( (rr.tctr.qtype != TYPE_RRSIG) || ((rr.tctr.qtype == TYPE_RRSIG) && (GET_U16_AT_P(ZDB_RECORD_PTR_RDATAPTR(&ttlrdata)) != TYPE_NSEC3)) ) ) { } */ ++changes; } else { if(top > zone->origin_vector.size) { const u8 *above_fqdn = fqdn; for(int i = 1; i < top - zone->origin_vector.size; ++i) { zdb_rr_label *above = zdb_rr_label_find_exact(zone->apex, &labels[i], top - zone->origin_vector.size - 1 - i); if(above != NULL) { if(btree_notempty(above->resource_record_set)) { break; } } above_fqdn += above_fqdn[0] + 1; nsec3replay.vtbl->record_del(&nsec3replay, above_fqdn, TYPE_NONE, NULL); } zdb_rr_label *rr_label = zdb_rr_label_find_exact(zone->apex, labels, (top - zone->origin_vector.size) - 1); if(rr_label != NULL) { zdb_rr_label_forall_children_of_fqdn(rr_label, fqdn, zdb_icmtl_replay_commit_label_forall_nsec3_del_cb, &nsec3replay); } } } #endif #if ZDB_HAS_NSEC_SUPPORT // 0 : proceed // 1 : ignore // ? : error if(!added_in_chain && (added_in_chain = nsecreplay.vtbl->record_del(&nsecreplay, fqdn, rr.tctr.qtype, &ttlrdata) != 0)) { ++changes; } //else #endif if(!added_in_chain) switch(rr.tctr.qtype) { case TYPE_SOA: { rdata_desc rdata = {TYPE_SOA, ttlrdata.rdata_size, ttlrdata.rdata_pointer}; log_info("journal: %{dnsname}: SOA: del %{dnsname} %{typerdatadesc}", zone->origin, fqdn, &rdata); s32 m1 = (top - zone->origin_vector.size) - 1; if(m1 == -1) { if(FAIL(ret = zdb_record_delete_exact(&zone->apex->resource_record_set, TYPE_SOA, &ttlrdata))) /* FB done, APEX : no delegation, source is the journal */ { if(!did_remove_soa) { log_err("journal: %{dnsname}: SOA: %r", zone->origin, ret); } } } else { if(FAIL(ret = zdb_rr_label_delete_record_exact(zone, labels, (top - zone->origin_vector.size) - 1, rr.tctr.qtype, &ttlrdata))) // source is journal { if(!did_remove_soa) { log_err("journal: %{dnsname}: SOA: (2) %r", zone->origin, ret); } } } break; } default: { #if ZDB_HAS_NSEC3_SUPPORT // NSEC3 if(rr.tctr.qtype != TYPE_NSEC3) { if((rr.tctr.qtype != TYPE_RRSIG) && (rrsig_get_type_covered_from_rdata(rr.rdata, rr.rdata_size) != TYPE_NSEC3)) { if(ptr_set_avl_find(&downed_fqdn, fqdn) == NULL) { ptr_set_avl_insert(&downed_fqdn, dnsname_dup(fqdn)); } } } else { if(!NSEC3_RDATA_IS_OPTOUT(rr.rdata)) { zone->_flags &= ~ZDB_ZONE_HAS_OPTOUT_COVERAGE; } } #endif if(FAIL(ret = zdb_rr_label_delete_record_exact(zone, labels, (top - zone->origin_vector.size) - 1, rr.tctr.qtype, &ttlrdata))) // source is journal { // signatures can be removed automatically by maintenance if((rr.tctr.qtype != TYPE_RRSIG) && (ret != ZDB_ERROR_KEY_NOTFOUND)) { log_err("journal: %{dnsname}: del %{dnsrr}", zone->origin, &rr); log_err("journal: %{dnsname}: %{dnstype}: %r", zone->origin, &rr.tctr.qtype, ret); } else { log_debug("journal: %{dnsname}: del %{dnsrr}", zone->origin, &rr); log_debug("journal: %{dnsname}: %{dnstype}: %r", zone->origin, &rr.tctr.qtype, ret); } } } } } else { /* * "TO ADD" record */ bool added_in_chain = FALSE; #if ZDB_HAS_NSEC3_SUPPORT // returns the number of changes taken into account (0 or 1) // 0 : proceed // 1 : ignore // ? : error if((added_in_chain = (nsec3replay.vtbl->record_add(&nsec3replay, fqdn, rr.tctr.qtype, &ttlrdata) != 0))) { ++changes; } else { if( (top > zone->origin_vector.size) && (rr.tctr.qtype != TYPE_NSEC3) && ( (rr.tctr.qtype != TYPE_RRSIG) || ((rr.tctr.qtype == TYPE_RRSIG) && (GET_U16_AT_P(ZDB_RECORD_PTR_RDATAPTR(&ttlrdata)) != TYPE_NSEC3)) ) ) { const u8 *above_fqdn = fqdn; for(int i = 1; i < top - zone->origin_vector.size; ++i) { zdb_rr_label *above = zdb_rr_label_find_exact(zone->apex, &labels[i], top - zone->origin_vector.size - 1 - i); if(above != NULL) { if(btree_notempty(above->resource_record_set)) { break; } } above_fqdn += above_fqdn[0] + 1; nsec3replay.vtbl->record_add(&nsec3replay, above_fqdn, TYPE_NONE, NULL); } zdb_rr_label *rr_label = zdb_rr_label_find_exact(zone->apex, labels, (top - zone->origin_vector.size) - 1); if(rr_label != NULL) { zdb_rr_label_forall_children_of_fqdn(rr_label, fqdn, zdb_icmtl_replay_commit_label_forall_nsec3_add_cb, &nsec3replay); } } } #endif #if ZDB_HAS_NSEC_SUPPORT // returns the number of changes taken into account (0 or 1) // 0 : proceed // 1 : ignore // ? : error if(!added_in_chain && (added_in_chain = (nsecreplay.vtbl->record_add(&nsecreplay, fqdn, rr.tctr.qtype, &ttlrdata) != 0))) { ++changes; } //else #endif if(!added_in_chain) switch(rr.tctr.qtype) { #if ZDB_HAS_NSEC3_SUPPORT case TYPE_NSEC3CHAINSTATE: { // create chain if missing ... nsec3_zone_add_from_rdata(zone, rr.rdata_size, rr.rdata); // add the record zdb_packed_ttlrdata *packed_ttlrdata; ZDB_RECORD_ZALLOC_EMPTY(packed_ttlrdata, ttlrdata.ttl, rr.rdata_size); packed_ttlrdata->next = NULL; MEMCOPY(ZDB_PACKEDRECORD_PTR_RDATAPTR(packed_ttlrdata), rr.rdata, rr.rdata_size); zdb_zone_record_add(zone, labels, top, rr.tctr.qtype, packed_ttlrdata); // class is implicit, flow verified break; } #endif // ZDB_HAS_NSEC3_SUPPORT # default: { zdb_packed_ttlrdata *packed_ttlrdata; ZDB_RECORD_ZALLOC_EMPTY(packed_ttlrdata, ttlrdata.ttl, rr.rdata_size); packed_ttlrdata->next = NULL; MEMCOPY(ZDB_PACKEDRECORD_PTR_RDATAPTR(packed_ttlrdata), rr.rdata, rr.rdata_size); #if ICMTL_DUMP_JOURNAL_RECORDS rdata_desc type_len_rdata = {rr.tctr.qtype, rr.rdata_size, ZDB_PACKEDRECORD_PTR_RDATAPTR(packed_ttlrdata) }; log_debug("journal: add %{dnsname} %{typerdatadesc}", fqdn, &type_len_rdata); logger_flush(); #endif if(rr.tctr.qtype == TYPE_SOA) { rr_soa_get_serial(ZDB_PACKEDRECORD_PTR_RDATAPTR(packed_ttlrdata), ZDB_PACKEDRECORD_PTR_RDATASIZE(packed_ttlrdata), current_serialp); rdata_desc rdata = {TYPE_SOA, ZDB_PACKEDRECORD_PTR_RDATASIZE(packed_ttlrdata), ZDB_PACKEDRECORD_PTR_RDATAPTR(packed_ttlrdata)}; log_info("journal: %{dnsname}: SOA: add %{dnsname} %{typerdatadesc}", zone->origin, fqdn, &rdata); } zdb_zone_record_add(zone, labels, top, rr.tctr.qtype, packed_ttlrdata); // class is implicit, flow verified } } } // end if ADD changes++; } /* * Yes, I know. If 2^32 changes (add batch + del batch) occurs then it will be seen as an error ... */ if(ISOK(changes)) { #if ZDB_HAS_NSEC3_SUPPORT && ZDB_HAS_NSEC_SUPPORT if(has_nsec3 && has_nsec) { log_warn("journal: %{dnsname}: both NSEC3 and NSEC operations happened, which is not supported by YADIFA. Keeping the original one.", zone->origin); has_nsec3 = zdb_zone_is_nsec3(zone); has_nsec = zdb_zone_is_nsec(zone); } #endif #if ZDB_HAS_NSEC3_SUPPORT nsec3replay.vtbl->execute(&nsec3replay); #endif #if ZDB_HAS_NSEC_SUPPORT nsecreplay.vtbl->execute(&nsecreplay); #endif } #if ZDB_HAS_NSEC3_SUPPORT // has_nsec3 = zdb_zone_is_nsec3(zone); nsec3replay.vtbl->finalise(&nsec3replay); #endif #if ZDB_HAS_NSEC_SUPPORT // has_nsec = zdb_zone_is_nsec(zone); nsecreplay.vtbl->finalise(&nsecreplay); #endif dns_resource_record_clear(&rr); return changes; }
void dnscore_finalize() { /* * No need to "finalize" format, dnsformat and rfc */ if(dnscore_finalizing) { /* OOPS : ALREADY BUSY SHUTTING DOWN */ /* DO NOT USE LOGGER HERE ! */ return; } dnscore_finalizing = TRUE; dnscore_shutdown(); #ifndef NDEBUG log_debug("exit: destroying the thread pool"); #endif logger_flush(); thread_pool_destroy(); #ifdef DEBUG log_debug("exit: bye (pid=%hd)", getpid()); logger_flush(); #endif scheduler_finalize(); logger_flush(); logger_finalize(); /** @note does a logger_stop */ logger_handle_finalize(); #ifndef NDEBUG /* * It may not be required right now, but in case the stdstream are filtered/buffered * this will flush them. */ #if HAS_TSIG_SUPPORT tsig_finalize(); #endif stdstream_flush_both_terms(); error_unregister_all(); rfc_finalize(); format_class_finalize(); #endif #ifndef NDEBUG #if ZDB_DEBUG_MALLOC != 0 debug_stat(TRUE); #endif #endif stdstream_flush_both_terms(); output_stream_close(&__termerr__); output_stream_close(&__termout__); }
ya_result scheduler_do_next_job() { /** @todo use the pool counters * _ Readers * _ Writers * _ Current Task : I can have a task that works bit by bit and continues until the last bit is done (RRSIG) */ /* Dequeue a job */ if(threaded_queue_size(&scheduler_queue) == 0) { return SCHEDULER_TASK_NOTHING; } scheduler_task *task = threaded_queue_dequeue(&scheduler_queue); /* Do (part) of the job */ scheduler_task_callback *callback = task->task; void* args = task->args; free(task); ya_result return_code; switch(return_code = callback(args)) { default: /* An error occurred */ log_err("scheduler: unexpected callback return code %r", return_code); case SCHEDULER_TASK_FINISHED: #ifndef NDEBUG log_debug("scheduler: task finished"); #endif /** * Retrieve and start the next thread * * @todo EXCEPT IF A SHUTDOWN HAS BEEN REQUESTED ? */ case SCHEDULER_TASK_DEQUEUE_DELAYED: if(dnscore_shuttingdown()) { log_info("scheduler: shutdown in progress : ignoring next job"); logger_flush(); return STOPPED_BY_APPLICATION_SHUTDOWN; } pthread_mutex_lock(&scheduler_delayed_queue_mutex); scheduler_thread_running = FALSE; if(!scheduler_thread_queue_isempty(&scheduler_delayed_queue)) { scheduler_thread* thread = scheduler_thread_queue_dequeue(&scheduler_delayed_queue); #ifndef NDEBUG log_debug("scheduler: dequeued thread %s::(%p, %p, %p, %p@%u)", thread->categoryname, thread->task_init, thread->task, thread->args, thread, thread->debug_count); log_debug("scheduler: starting thread %u", thread->debug_count); log_debug("scheduler: next thread init"); #endif if(thread->task_init != NULL) { thread->task_init(thread->args); } #ifndef NDEBUG log_debug("scheduler: next thread ready"); #endif if(thread->task != NULL) { #ifndef NDEBUG log_debug("scheduler: next thread start"); #endif scheduler_thread_running = TRUE; thread_pool_schedule_job(thread->task, thread->args, &scheduler_threads_counter, thread->categoryname); } free(thread); } pthread_mutex_unlock(&scheduler_delayed_queue_mutex); break; case SCHEDULER_TASK_PROGRESS: /* NOP */ #ifndef NDEBUG log_debug("scheduler: task progress"); #endif break; } return return_code; }
static void signal_handler(int signo, siginfo_t* info, void* context) { /* int status; int i; */ /* ------------------------------------------------------------ */ switch(signo) { case SIGHUP: { signal_task_logger_handle_reopen_all(); break; } case SIGUSR1: { /* write all (dirty) zones to disk */ signal_task_database_save_all_zones_to_disk(); break; } case SIGUSR2: { // Used to break a syscall (sync) break; } case SIGINT: case SIGTERM: { /* * We are shutting down : ignore other "command" signals */ signal(SIGHUP, SIG_IGN); signal(SIGUSR1, SIG_IGN); signal(SIGINT, SIG_IGN); signal(SIGTERM, SIG_IGN); signal_task_shutdown(); break; } #if SIGNAL_HOOK_COREDUMP == 0 case SIGBUS: case SIGFPE: case SIGILL: case SIGSEGV: { signal(signo, SIG_DFL); if(sigsegv_trytrace) { char filepath[1024]; FILE *f; /* So if we crashed while trying to dump, we will not do it anymore */ sigsegv_trytrace = FALSE; snprintf(filepath, sizeof(filepath), "%ssig%i.%i", config->log_path, signo, getpid()); f = fopen(filepath, "a+"); if(f == NULL) { snprintf(filepath, sizeof(filepath), "/tmp/yadifa.sig%i.%i", signo, getpid()); f = fopen(filepath, "a+"); } if(f != NULL) { #if defined(__linux__) void* buffer[MAXTRACE]; char** strings; int n = backtrace(buffer, MAXTRACE); int i; time_t now = time(NULL); fprintf(f, "Signal %i at time=%li for address %p\n", signo, now, info->si_addr); fflush(f); strings = backtrace_symbols(buffer, n); if(strings != NULL) { for(i = 0; i < n; i++) { fprintf(f, "\t[%3i]: %s\n", i, strings[i]); } } else { fprintf(f, "No backtrace available (%s)\n", strerror(errno)); } fflush(f); fprintf(f, "pid: %i\n", getpid()); fprintf(f, "thread id: %d", (u32)pthread_self()); #else fprintf(f, "Got signal %i. No backtrace available\n", signo); #endif fclose(f); } /** * Do NOT free(strings) : * If the memory is corrupted, this is one more chance to crash * */ } /* There COULD be some relevant information in the logger */ /* try to flush it */ if(sigsegv_tryloggerflush) { sigsegv_tryloggerflush = FALSE; logger_flush(); log_err("CRITICAL ERROR"); logger_flush(); } /* trigger the original signal (to dump a core if possible ) */ raise(signo); /* should never be reached : Exit without disabling stuff (no atexit registered function called) */ _exit(EXIT_CODE_SELFCHECK_ERROR); break; } #endif /* case SIGUSR2: case SIGCHLD: */ default: { break; } } }