may be I found and fixed the memory leak ... may be
This commit is contained in:
parent
5a26ac47f4
commit
1aa603aff2
@ -6,7 +6,7 @@ port = 8887
|
|||||||
; plugin_dir = /home/who/Sources/sf/smmapdfw
|
; plugin_dir = /home/who/Sources/sf/smmapdfw
|
||||||
; plugins = test_worker1 test_worker2 verifier cyruscheck lua_worker
|
; plugins = test_worker1 test_worker2 verifier cyruscheck lua_worker
|
||||||
plugins = verifier
|
plugins = verifier
|
||||||
enable_stats = 1
|
enable_stats = 0
|
||||||
enable_snmp = 1
|
enable_snmp = 1
|
||||||
|
|
||||||
; disables the netstring codec, only for debugging in the development
|
; disables the netstring codec, only for debugging in the development
|
||||||
|
@ -50,6 +50,7 @@
|
|||||||
#include "htbuffer.h"
|
#include "htbuffer.h"
|
||||||
|
|
||||||
#include "stats.h"
|
#include "stats.h"
|
||||||
|
#include "dvl.h"
|
||||||
|
|
||||||
#define SMM_LOCAL_PERM_NOK 101
|
#define SMM_LOCAL_PERM_NOK 101
|
||||||
#define SMM_LOCAL_TEMP_NOK 102
|
#define SMM_LOCAL_TEMP_NOK 102
|
||||||
@ -124,28 +125,11 @@ struct verify_work_handle_s {
|
|||||||
ht_queue_t *terminator_queue;
|
ht_queue_t *terminator_queue;
|
||||||
verify_container_handle_t *vch;
|
verify_container_handle_t *vch;
|
||||||
|
|
||||||
int whereAreWe1;
|
int worker_cnt;
|
||||||
int whereAreWe2;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct verify_work_handle_s verify_work_handle_t;
|
typedef struct verify_work_handle_s verify_work_handle_t;
|
||||||
|
|
||||||
/* --- debugging ------------------------------------- */
|
|
||||||
verify_work_handle_t *lastVerifyWorkHandle = NULL;
|
|
||||||
void showLastVerifyWorkHandleDetails(int signum) {
|
|
||||||
printf("showLastVerifyWorkHandleDetails:\n");
|
|
||||||
printf(" address: %p\n, lastVerifyWorkHandle");
|
|
||||||
if (lastVerifyWorkHandle != NULL) {
|
|
||||||
printf(" debug step: %d\n", lastVerifyWorkHandle->whereAreWe1);
|
|
||||||
printf(" debug sub step: %d\n", lastVerifyWorkHandle->whereAreWe2);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#define DEBUG_INSTALL do { signal(SIGUSR2, showLastVerifyWorkHandleDetails); } while(0)
|
|
||||||
#define DEBUG_INIT do { lastVerifyWorkHandle->whereAreWe1 = 0; lastVerifyWorkHandle->whereAreWe2 = 0; } while(0)
|
|
||||||
#define DEBUG_SUB_STEP_RESET do {lastVerifyWorkHandle->whereAreWe2 = 0; } while(0)
|
|
||||||
#define DEBUG_STEP do { lastVerifyWorkHandle->whereAreWe1++; } while(0)
|
|
||||||
#define DEBUG_SUB_STEP do { lastVerifyWorkHandle->whereAreWe2++; } while(0)
|
|
||||||
/* --------------------------------------------------- */
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -179,6 +163,7 @@ struct worker_thread_s {
|
|||||||
|
|
||||||
typedef struct worker_thread_s worker_thread_t;
|
typedef struct worker_thread_s worker_thread_t;
|
||||||
|
|
||||||
|
|
||||||
struct mydata_s {
|
struct mydata_s {
|
||||||
int result;
|
int result;
|
||||||
char output[1];
|
char output[1];
|
||||||
@ -276,31 +261,31 @@ int verify_work_setup(void *handle, void **work_handle) {
|
|||||||
pthread_cond_init(vwh->result_cond, NULL);
|
pthread_cond_init(vwh->result_cond, NULL);
|
||||||
vwh->terminator_queue = (ht_queue_t*) htmalloc(sizeof(ht_queue_t));
|
vwh->terminator_queue = (ht_queue_t*) htmalloc(sizeof(ht_queue_t));
|
||||||
queue_init(vwh->terminator_queue);
|
queue_init(vwh->terminator_queue);
|
||||||
|
vwh->worker_cnt = 0;
|
||||||
vwh->vch = (verify_container_handle_t*)handle;
|
vwh->vch = (verify_container_handle_t*)handle;
|
||||||
|
|
||||||
*work_handle = vwh;
|
*work_handle = vwh;
|
||||||
|
|
||||||
DEBUG_INSTALL;
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int verify_work_destroy(void *handle, void *work_handle) {
|
int verify_work_destroy(void *handle, void *work_handle) {
|
||||||
|
verify_container_handle_t *vch = (verify_container_handle_t*)handle;
|
||||||
verify_work_handle_t *vwh = (verify_work_handle_t*)work_handle;
|
verify_work_handle_t *vwh = (verify_work_handle_t*)work_handle;
|
||||||
worker_thread_t *wt;
|
worker_thread_t *wt;
|
||||||
checker_thread_t *ct;
|
checker_thread_t *ct;
|
||||||
int cnt, cnt2, err;
|
int err;
|
||||||
|
|
||||||
syslog(LOG_DEBUG, "verify (%p) verify_work_destroy: was %d times used", work_handle, vwh->id);
|
syslog(LOG_DEBUG, "verify (%p) verify_work_destroy: was %d times used", work_handle, vwh->id);
|
||||||
|
|
||||||
/* The terminator_queue must be drained until id_counter is zero again */
|
while (vwh->worker_cnt != 0) {
|
||||||
cnt = vwh->id;
|
syslog(LOG_DEBUG, "verify (%p) verify_work_destroy, %d worker thread in queue, waiting for it",
|
||||||
while (cnt != 0) {
|
work_handle, vwh->worker_cnt);
|
||||||
syslog(LOG_DEBUG, "verify (%p) verify_work_destroy, %d thread in queue, waiting for it",
|
|
||||||
work_handle, cnt);
|
|
||||||
wt = (worker_thread_t*) queue_get_wait(vwh->terminator_queue);
|
wt = (worker_thread_t*) queue_get_wait(vwh->terminator_queue);
|
||||||
|
|
||||||
cnt2 = wt->checker_cnt;
|
while (wt->checker_cnt != 0) {
|
||||||
while (cnt2 != 0) {
|
syslog(LOG_DEBUG, "verify (%p) verify_work_destroy, %d checker thread in queue, waiting for it",
|
||||||
|
work_handle, wt->checker_cnt);
|
||||||
ct = (checker_thread_t*) queue_get_wait(wt->checker_terminator_queue);
|
ct = (checker_thread_t*) queue_get_wait(wt->checker_terminator_queue);
|
||||||
/* clean up the checker stuff */
|
/* clean up the checker stuff */
|
||||||
|
|
||||||
@ -312,7 +297,7 @@ int verify_work_destroy(void *handle, void *work_handle) {
|
|||||||
free(ct->output);
|
free(ct->output);
|
||||||
free(ct);
|
free(ct);
|
||||||
|
|
||||||
cnt2--;
|
wt->checker_cnt--;
|
||||||
}
|
}
|
||||||
|
|
||||||
err = pthread_join(wt->thread, NULL);
|
err = pthread_join(wt->thread, NULL);
|
||||||
@ -330,7 +315,7 @@ int verify_work_destroy(void *handle, void *work_handle) {
|
|||||||
|
|
||||||
free(wt);
|
free(wt);
|
||||||
|
|
||||||
cnt--;
|
vwh->worker_cnt--;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Free the members of the work_handle */
|
/* Free the members of the work_handle */
|
||||||
@ -353,6 +338,19 @@ void cache_insert(verify_work_handle_t *vwh, const char *address, int result, co
|
|||||||
int mydata_size;
|
int mydata_size;
|
||||||
mydata_t *mydata;
|
mydata_t *mydata;
|
||||||
|
|
||||||
|
if (vwh == NULL) {
|
||||||
|
syslog(LOG_CRIT, "cache_insert: vwh is NULL");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (address == NULL) {
|
||||||
|
syslog(LOG_CRIT, "cache_insert: address is NULL");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (output == NULL) {
|
||||||
|
syslog(LOG_CRIT, "cache_insert: output is NULL");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (NULL != vwh->vch->cache) {
|
if (NULL != vwh->vch->cache) {
|
||||||
syslog(LOG_DEBUG, "verify (%p) cache_insert: inserting %s -> %d, %s", vwh, address, result, output);
|
syslog(LOG_DEBUG, "verify (%p) cache_insert: inserting %s -> %d, %s", vwh, address, result, output);
|
||||||
mydata_size = (sizeof(mydata_t) + (sizeof(char) * (strlen(output) + 1)));
|
mydata_size = (sizeof(mydata_t) + (sizeof(char) * (strlen(output) + 1)));
|
||||||
@ -371,6 +369,15 @@ int cache_lookup(verify_work_handle_t *vwh, const char* address, int *result, ch
|
|||||||
int ret, res = -1;
|
int ret, res = -1;
|
||||||
int mydata_size;
|
int mydata_size;
|
||||||
|
|
||||||
|
if (vwh == NULL) {
|
||||||
|
syslog(LOG_CRIT, "cache_lookup: vwh is NULL");
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
if (address == NULL) {
|
||||||
|
syslog(LOG_CRIT, "cache_lookup: address is NULL");
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
if (NULL != vwh->vch->cache) {
|
if (NULL != vwh->vch->cache) {
|
||||||
syslog(LOG_DEBUG, "verify (%p) cache_lookup: Looking up %s", vwh, address);
|
syslog(LOG_DEBUG, "verify (%p) cache_lookup: Looking up %s", vwh, address);
|
||||||
ret = htcache_lookup(vwh->vch->cache, address, (char**) &mydata, &mydata_size);
|
ret = htcache_lookup(vwh->vch->cache, address, (char**) &mydata, &mydata_size);
|
||||||
@ -414,12 +421,12 @@ int cache_lookup(verify_work_handle_t *vwh, const char* address, int *result, ch
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#define PERM_NOK_RETURN(msg) \
|
#define PERM_NOK_RETURN(msg) \
|
||||||
syslog(LOG_ERR, "verify (%p) verify_work: %s", vwh, msg); \
|
syslog(LOG_ERR, "verify (%p) verify_work: %s", vwh, msg); \
|
||||||
htbuffer_strcat(output, "verify_work: "); \
|
htbuffer_strcat(output, "verify_work: "); \
|
||||||
htbuffer_strcat(output, msg); \
|
htbuffer_strcat(output, msg); \
|
||||||
return SMM_PERM_NOK;
|
return SMM_PERM_NOK;
|
||||||
#define TEMP_NOK_RETURN(msg) \
|
#define TEMP_NOK_RETURN(msg) \
|
||||||
syslog(LOG_ERR, "verify (%p) verify_work: %s", vwh, msg); \
|
syslog(LOG_ERR, "verify (%p) verify_work: %s", vwh, msg); \
|
||||||
htbuffer_strcat(output, "verify_work: "); \
|
htbuffer_strcat(output, "verify_work: "); \
|
||||||
htbuffer_strcat(output, msg); \
|
htbuffer_strcat(output, msg); \
|
||||||
return SMM_TEMP_NOK;
|
return SMM_TEMP_NOK;
|
||||||
@ -432,8 +439,18 @@ int verify_work(void *handle, void *work_handle, char *input, htbuffer_t *output
|
|||||||
verify_work_handle_t *vwh = (verify_work_handle_t*) work_handle;
|
verify_work_handle_t *vwh = (verify_work_handle_t*) work_handle;
|
||||||
struct timespec ts;
|
struct timespec ts;
|
||||||
|
|
||||||
lastVerifyWorkHandle = vwh;
|
if (handle == NULL) {
|
||||||
DEBUG_INIT;
|
TEMP_NOK_RETURN("handle is NULL");
|
||||||
|
}
|
||||||
|
if (work_handle == NULL) {
|
||||||
|
TEMP_NOK_RETURN("work_handle is NULL");
|
||||||
|
}
|
||||||
|
if (input == NULL) {
|
||||||
|
TEMP_NOK_RETURN("input is NULL");
|
||||||
|
}
|
||||||
|
if (output == NULL) {
|
||||||
|
TEMP_NOK_RETURN("output is NULL");
|
||||||
|
}
|
||||||
|
|
||||||
syslog(LOG_DEBUG, "verify (%p) verify_work: going to verify %s\n", vwh, input);
|
syslog(LOG_DEBUG, "verify (%p) verify_work: going to verify %s\n", vwh, input);
|
||||||
|
|
||||||
@ -455,47 +472,39 @@ int verify_work(void *handle, void *work_handle, char *input, htbuffer_t *output
|
|||||||
wt->checker_cnt = 0;
|
wt->checker_cnt = 0;
|
||||||
wt->vwh = work_handle;
|
wt->vwh = work_handle;
|
||||||
|
|
||||||
DEBUG_STEP; // 1
|
|
||||||
|
|
||||||
syslog(LOG_DEBUG, "verify (%p) verify_work: going to start worker thread, id=%d",
|
syslog(LOG_DEBUG, "verify (%p) verify_work: going to start worker thread, id=%d",
|
||||||
vwh, vwh->id);
|
vwh, vwh->id);
|
||||||
DEBUG_STEP; // 2
|
|
||||||
|
|
||||||
pthread_mutex_lock(vwh->result_mutex);
|
pthread_mutex_lock(vwh->result_mutex);
|
||||||
DEBUG_STEP; // 3
|
|
||||||
err = pthread_create(&tid, NULL, &worker_thread, wt);
|
err = pthread_create(&tid, NULL, &worker_thread, wt);
|
||||||
DEBUG_STEP; // 4
|
if (0 != err) {
|
||||||
if (-1 == err) {
|
incStatCounter(vch->statCounter, STAT_CNT_VERIFIER_WORKER_THREADS_FAILED);
|
||||||
incStatCounter(vwh->vch->statCounter, STAT_CNT_VERIFIER_WORKER_THREADS_FAILED);
|
|
||||||
free(wt->input);
|
free(wt->input);
|
||||||
free(wt);
|
free(wt);
|
||||||
|
wt = NULL;
|
||||||
|
pthread_mutex_unlock(vwh->result_mutex);
|
||||||
PERM_NOK_RETURN("unable to create worker thread");
|
PERM_NOK_RETURN("unable to create worker thread");
|
||||||
|
} else {
|
||||||
|
vwh->worker_cnt++;
|
||||||
}
|
}
|
||||||
DEBUG_STEP; // 5
|
|
||||||
|
|
||||||
|
|
||||||
syslog(LOG_DEBUG, "verify (%p) verify_work: waiting for result", vwh);
|
syslog(LOG_DEBUG, "verify (%p) verify_work: waiting for result", vwh);
|
||||||
ts.tv_sec = time(0) + vch->timeout_result;
|
ts.tv_sec = time(0) + vch->timeout_result;
|
||||||
ts.tv_nsec = 0;
|
ts.tv_nsec = 0;
|
||||||
DEBUG_STEP; // 6
|
|
||||||
|
|
||||||
err = pthread_cond_timedwait(vwh->result_cond, vwh->result_mutex, &ts);
|
err = pthread_cond_timedwait(vwh->result_cond, vwh->result_mutex, &ts);
|
||||||
DEBUG_STEP; // 7
|
|
||||||
pthread_mutex_unlock(vwh->result_mutex);
|
pthread_mutex_unlock(vwh->result_mutex);
|
||||||
DEBUG_STEP; // 8
|
|
||||||
if (ETIMEDOUT == err) {
|
if (ETIMEDOUT == err) {
|
||||||
|
printf("last worker: %p, %d\n", wt, wt->whereAreWe);
|
||||||
|
|
||||||
incStatCounter(vwh->vch->statCounter, STAT_CNT_VERIFIER_WORKER_THREADS_TIMEOUT);
|
incStatCounter(vwh->vch->statCounter, STAT_CNT_VERIFIER_WORKER_THREADS_TIMEOUT);
|
||||||
TEMP_NOK_RETURN("worker thread timed out");
|
TEMP_NOK_RETURN("worker thread timed out");
|
||||||
}
|
}
|
||||||
DEBUG_STEP; // 9
|
|
||||||
|
|
||||||
|
|
||||||
// snprintf(output, ANSWER_BUFSIZE, vwh->result->output);
|
// snprintf(output, ANSWER_BUFSIZE, vwh->result->output);
|
||||||
htbuffer_strcpy(output, vwh->result->output);
|
htbuffer_strcpy(output, vwh->result->output);
|
||||||
DEBUG_STEP; // 10
|
|
||||||
|
|
||||||
free(vwh->result->output);
|
free(vwh->result->output);
|
||||||
DEBUG_STEP; // 11
|
|
||||||
|
|
||||||
return vwh->result->result;
|
return vwh->result->result;
|
||||||
}
|
}
|
||||||
@ -507,6 +516,11 @@ static unsigned int *get_mx_ip_addresses(char *domain) {
|
|||||||
int i = 0;
|
int i = 0;
|
||||||
unsigned int *addresses = NULL;
|
unsigned int *addresses = NULL;
|
||||||
|
|
||||||
|
if (NULL == domain) {
|
||||||
|
syslog(LOG_CRIT, "get_mx_ip_addresses: domain is NULL");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
mx_rdata = get_best_mx_rrs(domain);
|
mx_rdata = get_best_mx_rrs(domain);
|
||||||
if (NULL == mx_rdata) {
|
if (NULL == mx_rdata) {
|
||||||
syslog(LOG_DEBUG, "get_mx_ip_address: no mx at all");
|
syslog(LOG_DEBUG, "get_mx_ip_address: no mx at all");
|
||||||
@ -539,6 +553,11 @@ static unsigned int *get_mx_ip_addresses(char *domain) {
|
|||||||
|
|
||||||
|
|
||||||
static void *checker_thread(void *arg) {
|
static void *checker_thread(void *arg) {
|
||||||
|
if (arg == NULL) {
|
||||||
|
syslog(LOG_CRIT, "checker_thread: arg is NULL");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
static const char *UNEXPECTED_ERROR = "unexpected error in smtp dialog";
|
static const char *UNEXPECTED_ERROR = "unexpected error in smtp dialog";
|
||||||
static const char *TIMEOUT_ERROR = "timeout on smtp dialog";
|
static const char *TIMEOUT_ERROR = "timeout on smtp dialog";
|
||||||
static const char *ADDRESS_VALID = "address is valid";
|
static const char *ADDRESS_VALID = "address is valid";
|
||||||
@ -673,6 +692,11 @@ static void *checker_thread(void *arg) {
|
|||||||
|
|
||||||
|
|
||||||
static void *worker_thread(void *arg) {
|
static void *worker_thread(void *arg) {
|
||||||
|
if (arg == NULL) {
|
||||||
|
syslog(LOG_CRIT, "worker_thread: arg is NULL");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
worker_thread_t *wt = (worker_thread_t*) arg;
|
worker_thread_t *wt = (worker_thread_t*) arg;
|
||||||
char *domain_part;
|
char *domain_part;
|
||||||
unsigned int *mx_ip_addresses;
|
unsigned int *mx_ip_addresses;
|
||||||
@ -686,6 +710,9 @@ static void *worker_thread(void *arg) {
|
|||||||
static const char *DEFAULT_ANSWER = "default answer";
|
static const char *DEFAULT_ANSWER = "default answer";
|
||||||
static const char *NO_MX_AVAILABLE = "no MX available";
|
static const char *NO_MX_AVAILABLE = "no MX available";
|
||||||
static const char *NO_PERM_RESULT = "no checker returned permanent result";
|
static const char *NO_PERM_RESULT = "no checker returned permanent result";
|
||||||
|
static const char *INTERNAL_ERROR = "verifier internal error";
|
||||||
|
|
||||||
|
lastThing = wt;
|
||||||
|
|
||||||
syslog(LOG_DEBUG, "verify (%p) worker_thread %d started, %s",
|
syslog(LOG_DEBUG, "verify (%p) worker_thread %d started, %s",
|
||||||
wt->vwh, wt->id, wt->input);
|
wt->vwh, wt->id, wt->input);
|
||||||
@ -721,12 +748,6 @@ static void *worker_thread(void *arg) {
|
|||||||
} else {
|
} else {
|
||||||
for (i = 0; (*(mx_ip_addresses+i) != 0) && (i < wt->vwh->vch->max_checker_threads); i++) {
|
for (i = 0; (*(mx_ip_addresses+i) != 0) && (i < wt->vwh->vch->max_checker_threads); i++) {
|
||||||
unsigned int address = *(mx_ip_addresses+i);
|
unsigned int address = *(mx_ip_addresses+i);
|
||||||
syslog(LOG_DEBUG, "verify (%p) worker_thread: starting checker thread to %d.%d.%d.%d, for email-address %s",
|
|
||||||
wt->vwh,
|
|
||||||
(address&0xff000000)>>24, (address&0x00ff0000)>>16,
|
|
||||||
(address&0x0000ff00)>>8, (address&0x000000ff),
|
|
||||||
wt->input);
|
|
||||||
|
|
||||||
ct = (checker_thread_t*) htmalloc(sizeof(checker_thread_t));
|
ct = (checker_thread_t*) htmalloc(sizeof(checker_thread_t));
|
||||||
ct->id = i+1; /* id of ct should start with 1, same as id of wt */
|
ct->id = i+1; /* id of ct should start with 1, same as id of wt */
|
||||||
ct->ip_address = address;
|
ct->ip_address = address;
|
||||||
@ -735,12 +756,23 @@ static void *worker_thread(void *arg) {
|
|||||||
ct->result = SMM_TEMP_NOK;
|
ct->result = SMM_TEMP_NOK;
|
||||||
ct->checker_terminator_queue = wt->checker_terminator_queue;
|
ct->checker_terminator_queue = wt->checker_terminator_queue;
|
||||||
ct->vwh = wt->vwh;
|
ct->vwh = wt->vwh;
|
||||||
|
|
||||||
|
syslog(LOG_DEBUG, "verify (%p) worker_thread: starting checker thread (%p) to %d.%d.%d.%d, for email-address %s",
|
||||||
|
wt->vwh,
|
||||||
|
ct,
|
||||||
|
(address&0xff000000)>>24, (address&0x00ff0000)>>16,
|
||||||
|
(address&0x0000ff00)>>8, (address&0x000000ff),
|
||||||
|
wt->input);
|
||||||
|
|
||||||
|
|
||||||
err = pthread_create(&tid, NULL, &checker_thread, ct);
|
err = pthread_create(&tid, NULL, &checker_thread, ct);
|
||||||
if (-1 == err) {
|
if (0 != err) {
|
||||||
incStatCounter(ct->vwh->vch->statCounter, STAT_CNT_VERIFIER_CHECKER_THREADS_FAILED);
|
incStatCounter(ct->vwh->vch->statCounter, STAT_CNT_VERIFIER_CHECKER_THREADS_FAILED);
|
||||||
syslog(LOG_ERR, "verify (%p) worker_thread: unable to create checker thread", wt->vwh);
|
syslog(LOG_ERR, "verify (%p) worker_thread: unable to create checker thread: %d", wt->vwh, err);
|
||||||
free(ct);
|
free(ct);
|
||||||
|
ct = NULL;
|
||||||
|
wt->output = (char*) INTERNAL_ERROR;
|
||||||
|
result = SMM_LOCAL_TEMP_NOK;
|
||||||
} else {
|
} else {
|
||||||
wt->checker_cnt += 1;
|
wt->checker_cnt += 1;
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user