]> git.ipfire.org Git - thirdparty/knot-resolver.git/commitdiff
daemon/worker: cleanup and fixed early memset
authorMarek Vavruša <marek.vavrusa@nic.cz>
Wed, 15 Jul 2015 15:20:04 +0000 (17:20 +0200)
committerMarek Vavruša <marek.vavrusa@nic.cz>
Wed, 15 Jul 2015 15:20:15 +0000 (17:20 +0200)
contrib/config.h
contrib/ucw/lib.h
daemon/worker.c

index 4979e823286096e712a32935cdc7b1c78958b317..24732c7715c013bd1b818fd4699e52e6de480378 100644 (file)
@@ -1 +1,5 @@
-/* Dummy file, no real configuration here */
\ No newline at end of file
+/* Dummy file, no real configuration here */
+#define HAVE_ATTRIBUTE_COLD 1
+#define HAVE_ATTRIBUTE_NORETURN 1
+#define HAVE_ATTRIBUTE_PURE 1
+#define HAVE_ATTRIBUTE_UNUSED 1
\ No newline at end of file
index bd4612f106f24b0cd107bf791350caadc1abeec9..1363eb5aeb3e718397ddde98df9b527157ecc7e7 100644 (file)
@@ -87,7 +87,6 @@
 
 #ifdef __GNUC__
 
-#undef inline
 #define NONRET __attribute__((noreturn))                               /** Function does not return **/
 #define UNUSED __attribute__((unused))                                 /** Variable/parameter is knowingly unused **/
 #define CONSTRUCTOR __attribute__((constructor))                       /** Call function upon start of program **/
  * === Basic logging functions (see <<log:,Logging>> and <ucw/log.h> for more)
  ***/
 
-enum log_levels {                      /** The available log levels to pass to msg() and friends. **/
-  L_DEBUG=0,                           // 'D' - Debugging
-  L_INFO,                              // 'I' - Informational
-  L_WARN,                              // 'W' - Warning
-  L_ERROR,                             // 'E' - Error, but non-critical
-  L_INFO_R,                            // 'i' - An alternative set of levels for messages caused by remote events
-  L_WARN_R,                            // 'w'   (e.g., a packet received via network)
-  L_ERROR_R,                           // 'e'
-  L_FATAL,                             // '!' - Fatal error
-  L_MAX
-};
-
-#define LOG_LEVEL_NAMES P(DEBUG) P(INFO) P(WARN) P(ERROR) P(INFO_R) P(WARN_R) P(ERROR_R) P(FATAL)
-
-// Return the letter associated with a given severity level
-#define LS_LEVEL_LETTER(level) ("DIWEiwe!###"[( level )])
-
-#define L_SIGHANDLER   0x80000000      /** Avoid operations that are unsafe in signal handlers **/
-#define L_LOGGER_ERR   0x40000000      /** Used internally to avoid infinite reporting of logging errors **/
-
-/**
- * This is the basic printf-like function for logging a message.
- * The @flags contain the log level and possibly other flag bits (like `L_SIGHANDLER`).
- **/
-void msg(uint flags, const char *fmt, ...) FORMAT_CHECK(printf,2,3);
-void vmsg(uint flags, const char *fmt, va_list args);          /** A vararg version of msg(). **/
-void die(const char *, ...) NONRET FORMAT_CHECK(printf,1,2);   /** Log a fatal error message and exit the program. **/
-void vdie(const char *fmt, va_list args) NONRET;               /** va_list version of die() **/
-
-extern char *log_title;                        /** An optional log message title. Set to program name by log_init(). **/
-extern int log_pid;                    /** An optional PID printed in each log message. Set to 0 if it shouldn't be logged. **/
-extern void (*log_die_hook)(void);     /** An optional function called just before die() exists. **/   // API: log_die_hook
-
-void log_init(const char *argv0);      /** Set @log_title to the program name extracted from @argv[0]. **/
-void log_fork(void);                   /** Call after fork() to update @log_pid. **/
-void log_file(const char *name);       /** Establish logging to the named file. Also redirect stderr there. **/
-
-void assert_failed(const char *assertion, const char *file, int line) NONRET;
-void assert_failed_msg(const char *assertion, const char *file, int line, const char *fmt, ...) NONRET FORMAT_CHECK(printf,4,5);
-void assert_failed_noinfo(void) NONRET;
-
-#ifdef DEBUG_ASSERTS
-/**
- * Check an assertion. If the condition @x is false, stop the program with a fatal error.
- * Assertion checks are compiled only when `DEBUG_ASSERTS` is defined.
- **/
-#define ASSERT(x) ({ if (unlikely(!(x))) assert_failed(#x, __FILE__, __LINE__); 1; })
-
-/**
- * Check an assertion with a debug message. If the condition @cond is false,
- * print the message and stop the program with fatal error.
- * Assertion checks are compiled only when `DEBUG_ASSERTS` is defined.
- **/
-#define ASSERT_MSG(cond,str,x...) ({ if (unlikely(!(cond))) assert_failed_msg(#cond, __FILE__, __LINE__, str,##x); 1; })
-
-#else
-#define ASSERT(x) ({ if (__builtin_constant_p(x) && !(x)) assert_failed_noinfo(); 1; })
-#define ASSERT_MSG(cond,str,x...) ASSERT(cond)
-#endif
-
-#define COMPILE_ASSERT(name,x) typedef char _COMPILE_ASSERT_##name[!!(x)-1]
-
-#ifdef LOCAL_DEBUG
-#define DBG(x,y...) msg(L_DEBUG, x,##y)        /** If `LOCAL_DEBUG` is defined before including <ucw/lib.h>, log a debug message. Otherwise do nothing. **/
-/**
- * If `LOCAL_DEBUG` is defined before including <ucw/lib.h>, log current
- * file name and line number. Otherwise do nothing.
- **/
-#define DBG_SPOT msg(L_DEBUG, "%s:%d (%s)", __FILE__, __LINE__, __func__)
-#else
 #define DBG(x,y...) do { } while(0)
 #define DBG_SPOT do { } while(0)
-#endif
-
-#ifdef DEBUG_ASSERTS
-/**
- * Sometimes, we may want to check that a pointer points to a valid memory
- * location before we start using it for anything more complicated. This
- * macro checks pointer validity by reading the byte it points to.
- **/
-#define ASSERT_READABLE(ptr) ({ volatile char *__p = (ptr); *__p; })
-/** Like the previous macro, but it checks writeability, too. **/
-#define ASSERT_WRITEABLE(ptr) ({ volatile char *__p = (ptr); *__p = *__p; })
-#else
-#define ASSERT_READABLE(ptr) do { } while(0)
-#define ASSERT_WRITEABLE(ptr) do { } while(0)
-#endif
-
-/*** === Memory allocation ***/
-
-/*
- * Unfortunately, several libraries we might want to link to define
- * their own xmalloc and we don't want to interfere with them, hence
- * the renaming.
- */
-#define xmalloc ucw_xmalloc
-#define xrealloc ucw_xrealloc
-#define xfree ucw_xfree
-
-void *xmalloc(size_t) LIKE_MALLOC;             /** Allocate memory and die() if there is none. **/
-void *xrealloc(void *, size_t);                        /** Reallocate memory and die() if there is none. **/
-void xfree(void *);                            /** Free memory allocated by xmalloc() or xrealloc(). **/
-
-void *xmalloc_zero(size_t) LIKE_MALLOC;                /** Allocate memory and fill it by zeroes. **/
-char *xstrdup(const char *) LIKE_MALLOC;       /** Make a xmalloc()'ed copy of a string. Returns NULL for NULL string. **/
-
-/* bigalloc.c */
-
-void *page_alloc(u64 len) LIKE_MALLOC;         // Internal: allocates a multiple of CPU_PAGE_SIZE bytes with mmap
-void *page_alloc_zero(u64 len) LIKE_MALLOC;
-void page_free(void *start, u64 len);
-void *page_realloc(void *start, u64 old_len, u64 new_len);
-
-void *big_alloc(u64 len) LIKE_MALLOC;          /** Allocate a large memory block in the most efficient way available. **/
-void *big_alloc_zero(u64 len) LIKE_MALLOC;     /** Allocate and clear a large memory block. **/
-void big_free(void *start, u64 len);           /** Free block allocated by @big_alloc() or @big_alloc_zero(). **/
-
-/*** === Random numbers (random.c) ***/
-
-uint random_u32(void);                         /** Return a pseudorandom 32-bit number. **/
-uint random_max(uint max);                     /** Return a pseudorandom 32-bit number in range [0,@max). **/
-u64 random_u64(void);                          /** Return a pseudorandom 64-bit number. **/
-u64 random_max_u64(u64 max);                   /** Return a pseudorandom 64-bit number in range [0,@max). **/
+#define ASSERT(x)
 
 #endif
index 90bc9f71f518163d5ec9e2dd5c254ff913621da1..726477d073c01bed81e1a29335197e0f79625ffc 100644 (file)
@@ -17,7 +17,8 @@
 #include <uv.h>
 #include <libknot/packet/pkt.h>
 #include <libknot/internal/net.h>
-#include <ucw/mempool.h>
+#include <contrib/ucw/lib.h>
+#include <contrib/ucw/mempool.h>
 #if defined(__GLIBC__) && defined(_GNU_SOURCE)
 #include <malloc.h>
 #endif
@@ -99,6 +100,15 @@ static int parse_query(knot_pkt_t *query)
 
 static struct qr_task *qr_task_create(struct worker_ctx *worker, uv_handle_t *handle, knot_pkt_t *query, const struct sockaddr *addr)
 {
+       /* How much can client handle? */
+       size_t answer_max = KNOT_WIRE_MIN_PKTSIZE;
+       if (!addr) { /* TCP */
+               answer_max = KNOT_WIRE_MAX_PKTSIZE;
+       } else if (knot_pkt_has_edns(query)) { /* EDNS */
+               answer_max = MAX(knot_edns_get_payload(query->opt_rr), KNOT_WIRE_MIN_PKTSIZE);
+       }
+       size_t pktbuf_max = MAX(KNOT_EDNS_MAX_UDP_PAYLOAD, answer_max);
+
        /* Recycle available mempool if possible */
        mm_ctx_t pool = {
                .ctx = NULL,
@@ -111,38 +121,15 @@ static struct qr_task *qr_task_create(struct worker_ctx *worker, uv_handle_t *ha
                pool.ctx = mp_new (4 * CPU_PAGE_SIZE);
        }
 
-       /* Create worker task */
+       /* Create resolution task */
        struct engine *engine = worker->engine;
        struct qr_task *task = mm_alloc(&pool, sizeof(*task));
-       memset(task, 0, sizeof(*task));
        if (!task) {
                mp_delete(pool.ctx);
                return NULL;
        }
-       task->worker = worker;
+       /* Create packet buffers for answer and subrequests */
        task->req.pool = pool;
-       task->source.handle = handle;
-       if (addr) {
-               memcpy(&task->source.addr, addr, sockaddr_len(addr));
-       }
-
-       /* How much can client handle? */
-       size_t answer_max = KNOT_WIRE_MIN_PKTSIZE;
-       if (!addr) { /* TCP */
-               answer_max = KNOT_WIRE_MAX_PKTSIZE;
-       } else if (knot_pkt_has_edns(query)) { /* EDNS */
-               answer_max = knot_edns_get_payload(query->opt_rr);
-               if (answer_max < KNOT_WIRE_MIN_PKTSIZE) {
-                       answer_max = KNOT_WIRE_MIN_PKTSIZE;
-               }
-       }
-       /* How much space do we need for intermediate packets? */
-       size_t pktbuf_max = KNOT_EDNS_MAX_UDP_PAYLOAD;
-       if (pktbuf_max < answer_max) {
-               pktbuf_max = answer_max;
-       }
-
-       /* Create buffers */
        knot_pkt_t *pktbuf = knot_pkt_new(NULL, pktbuf_max, &task->req.pool);
        knot_pkt_t *answer = knot_pkt_new(NULL, answer_max, &task->req.pool);
        if (!pktbuf || !answer) {
@@ -151,10 +138,20 @@ static struct qr_task *qr_task_create(struct worker_ctx *worker, uv_handle_t *ha
        }
        task->req.answer = answer;
        task->next_query = pktbuf;
-
-       /* Start resolution */
+       task->next_handle = NULL;
+       task->iter_count = 0;
+       task->flags = 0;
+       task->worker = worker;
+       task->source.handle = handle;
        uv_timer_init(worker->loop, &task->timeout);
        task->timeout.data = task;
+       if (addr) {
+               memcpy(&task->source.addr, addr, sockaddr_len(addr));
+       } else {
+               task->source.addr.ip4.sin_family = AF_UNSPEC;
+       }
+
+       /* Start resolution */
        kr_resolve_begin(&task->req, &engine->resolver, answer);
        worker->stats.concurrent += 1;
        return task;
@@ -180,7 +177,7 @@ static void qr_task_free(uv_handle_t *handle)
        }
 #if defined(__GLIBC__) && defined(_GNU_SOURCE)
        /* Decommit memory every once in a while */
-       static size_t mp_delete_count = 0;
+       static int mp_delete_count = 0;
        if (++mp_delete_count == 100 * MP_FREELIST_SIZE) {
                malloc_trim(0);
                mp_delete_count = 0;
@@ -322,7 +319,7 @@ static int qr_task_step(struct qr_task *task, knot_pkt_t *packet)
        int state = kr_resolve_consume(&task->req, packet);
        while (state == KNOT_STATE_PRODUCE) {
                state = kr_resolve_produce(&task->req, &addr, &sock_type, next_query);
-               if (++task->iter_count > KR_ITER_LIMIT) {
+               if (unlikely(++task->iter_count > KR_ITER_LIMIT)) {
                        return qr_task_finalize(task, KNOT_STATE_FAIL);
                }
        }
@@ -330,10 +327,7 @@ static int qr_task_step(struct qr_task *task, knot_pkt_t *packet)
        /* We're done, no more iterations needed */
        if (state & (KNOT_STATE_DONE|KNOT_STATE_FAIL)) {
                return qr_task_finalize(task, state);
-       }
-
-       /* Not done, but no next address given. */
-       if (!addr || sock_type < 0) {
+       } else if (!addr || sock_type < 0) {
                return qr_task_step(task, NULL);
        }
 
@@ -346,17 +340,17 @@ static int qr_task_step(struct qr_task *task, knot_pkt_t *packet)
        /* Connect or issue query datagram */
        io_create(task->worker->loop, task->next_handle, sock_type);
        task->next_handle->data = task;
-       if (sock_type == SOCK_STREAM) {
+       if (sock_type == SOCK_DGRAM) {
+               if (qr_task_send(task, task->next_handle, addr, next_query) != 0) {
+                       return qr_task_step(task, NULL);
+               }
+       } else {
                struct ioreq *req = ioreq_take(task->worker);
                if (!req || uv_tcp_connect(&req->as.connect, (uv_tcp_t *)task->next_handle, addr, on_connect) != 0) {
                        ioreq_release(task->worker, req);
                        return qr_task_step(task, NULL);
                }
                req->as.connect.data = task;
-       } else {
-               if (qr_task_send(task, task->next_handle, addr, next_query) != 0) {
-                       return qr_task_step(task, NULL);
-               }
        }
 
        /* Start next step with timeout */