initial routine re-architecture to remove memory leak and improve

stability
This commit is contained in:
Sukchan Lee 2017-08-04 21:29:49 +09:00
parent 08f260f6d9
commit 772aefec7d
14 changed files with 443 additions and 271 deletions

View File

@ -231,8 +231,6 @@ status_t context_db_init(char *db_uri)
if (!self.db_client)
{
d_error("Failed to parse DB URI [%s]", db_uri);
context_db_final();
return CORE_ERROR;
}

View File

@ -273,7 +273,6 @@ typedef c_int32_t c_intptr_t;
* </PRE>
*/
#define THREAD_FUNC
#define PROC_FUNC
/**
* The public CORE functions are declared with CORE_DECLARE(), so they may

View File

@ -1,45 +0,0 @@
#ifndef __CORE_PROC_H__
#define __CORE_PROC_H__
#include "core.h"
#include "core_errno.h"
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
/** Opaque Thread structure. */
typedef c_uintptr_t proc_id;
typedef status_t (PROC_FUNC *proc_func_t)(proc_id id, void*);
/**
* Initialize Thread
*/
CORE_DECLARE(status_t) proc_init(void);
/**
* Finalize Thread
*/
CORE_DECLARE(status_t) proc_final(void);
/**
* Create a new proc of execution
*/
CORE_DECLARE(status_t) proc_create(proc_id *id,
proc_func_t start_func, proc_func_t stop_func,
void *data);
/**
* Delete a new proc of execution
* @param id The proc to delete
*/
CORE_DECLARE(status_t) proc_delete(proc_id id);
CORE_DECLARE(status_t) os_proc_get(void **theproc, proc_id id);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* ! __CORE_PROC_H__ */

View File

@ -7,11 +7,10 @@ libcoreunix_la_SOURCES = \
../../include/arch/unix/core_arch_file.h \
../../include/arch/unix/core_arch_mutex.h \
../../include/arch/unix/core_arch_semaphore.h \
../../include/arch/unix/core_arch_thread.h \
../../include/arch/unix/core_arch_proc.h
../../include/arch/unix/core_arch_thread.h
nodist_libcoreunix_la_SOURCES = \
cond.c file.c net_lib.c thread.c proc.c errorcodes.c mutex.c rwlock.c \
cond.c file.c net_lib.c thread.c errorcodes.c mutex.c rwlock.c \
start.c time.c semaphore.c signal.c pkbuf.c rand.c atomic.c
AM_CPPFLAGS = \

View File

@ -1,112 +0,0 @@
#define TRACE_MODULE _proc
#include "core.h"
#include "core_arch_proc.h"
#include "core_portable.h"
#include "core_errno.h"
#include "core_param.h"
#include "core_general.h"
#include "core_debug.h"
#include "core_pool.h"
#include "core_semaphore.h"
#include "core_signal.h"
pool_declare(proc_pool, proc_t, MAX_NUM_OF_PROC);
status_t proc_init(void)
{
pool_init(&proc_pool, MAX_NUM_OF_PROC);
return CORE_OK;
}
status_t proc_final(void)
{
pool_final(&proc_pool);
return CORE_OK;
}
status_t proc_create(proc_id *id,
proc_func_t start_func, proc_func_t stop_func,
void *data)
{
proc_t *new = NULL;
pool_alloc_node(&proc_pool, &new);
d_assert(new, return CORE_ENOMEM, "proc_pool(%d) is not enough\n",
MAX_NUM_OF_PROC);
memset(new, 0, sizeof(proc_id));
new->data = data;
new->start_func = start_func;
new->stop_func = stop_func;
semaphore_create(&new->sem1, 0);
semaphore_create(&new->sem2, 0);
new->proc = fork();
d_assert(new->proc >= 0, _exit(EXIT_FAILURE), "fork() failed");
if (new->proc == 0)
{
status_t rv;
new->proc = getpid();
semaphore_post(new->sem1);
rv = new->start_func((proc_id)new, new->data);
d_trace(3, "[%d] start_func done(rv = %d)\n", new->proc, rv);
semaphore_wait(new->sem2);
d_trace(3, "[%d] semaphore wait in child\n", new->proc);
if (rv == CORE_OK)
{
new->stop_func(new->proc, new->data);
d_trace(3, "[%d] stop_func done(rv = %d)\n", new->proc, rv);
}
semaphore_post(new->sem1);
semaphore_delete(new->sem1);
semaphore_delete(new->sem2);
pool_free_node(&proc_pool, new);
d_trace(3, "[%d] delete core proc memory in child\n", new->proc);
core_terminate();
d_trace(3, "[%d[ core proc terminate...done\n", new->proc);
_exit(EXIT_SUCCESS);
}
d_trace(3, "proc_create wait\n");
semaphore_wait(new->sem1);
d_trace(3, "proc_create done\n");
*id = (proc_id)new;
return CORE_OK;
}
status_t proc_delete(proc_id id)
{
proc_t *proc = (proc_t *)id;
#if 0
core_kill(proc->proc, SIGTERM);
d_trace(3, "core_kill done for %d\n", proc->proc);
#endif
semaphore_post(proc->sem2);
semaphore_wait(proc->sem1);
d_trace(3, "[%d] semaphore wait in parent\n", proc->proc);
semaphore_delete(proc->sem1);
semaphore_delete(proc->sem2);
pool_free_node(&proc_pool, proc);
d_trace(3, "[%d] delete core proc memory in parent\n", proc->proc);
return CORE_OK;
}

View File

@ -11,7 +11,6 @@
#include "core_rwlock.h"
#include "core_semaphore.h"
#include "core_thread.h"
#include "core_proc.h"
#include "core_net.h"
#include "core_file.h"
#include "core_pkbuf.h"
@ -46,7 +45,6 @@ status_t core_initialize(void)
rwlock_init();
atomic_init();
thread_init();
proc_init();
net_init();
file_init();
pkbuf_init();
@ -74,7 +72,6 @@ void core_terminate(void)
pkbuf_final();
file_final();
net_final();
proc_final();
thread_final();
atomic_final();
rwlock_final();

View File

@ -22,6 +22,29 @@ static void s6a_hook_cb_tree(enum fd_hook_type type, struct msg * msg,
if (s6a_hook_user_handler_instance)
s6a_hook_user_handler_instance(type, msg, peer, other, pmd, regdata);
switch(type) {
case HOOK_PEER_CONNECT_SUCCESS:
{
char protobuf[40];
if (peer) {
CHECK_FCT_DO(fd_peer_cnx_proto_info(peer, protobuf, sizeof(protobuf)), break );
} else {
protobuf[0] = '-';
protobuf[1] = '\0';
}
d_info("CONNECTED TO '%s' (%s):", peer_name, protobuf);
}
break;
default:
break;
}
if (TRACE_MODULE < 3)
{
pthread_mutex_unlock(&mtx);
return;
}
if (msg) {
CHECK_MALLOC_DO( fd_msg_dump_treeview(&buf, &len, NULL, msg, fd_g_config->cnf_dict, (type == HOOK_MESSAGE_PARSING_ERROR) ? 0 : 1, 1),

251
src/epc.c
View File

@ -1,27 +1,24 @@
#define TRACE_MODULE _epc_main
#include "core_general.h"
#include "core_debug.h"
#include "core_signal.h"
#include "core_semaphore.h"
#include "core_proc.h"
#include "context.h"
#include "app.h"
static proc_id pgw_proc = 0;
static status_t PROC_FUNC pgw_start_func(proc_id id, void *data);
static status_t PROC_FUNC pgw_stop_func(proc_id id, void *data);
static semaphore_id pgw_sem1;
static semaphore_id pgw_sem2;
static proc_id sgw_proc = 0;
static status_t PROC_FUNC sgw_start_func(proc_id id, void *data);
static status_t PROC_FUNC sgw_stop_func(proc_id id, void *data);
static semaphore_id sgw_sem1;
static semaphore_id sgw_sem2;
static proc_id hss_proc = 0;
static status_t PROC_FUNC hss_start_func(proc_id id, void *data);
static status_t PROC_FUNC hss_stop_func(proc_id id, void *data);
static semaphore_id hss_sem1;
static semaphore_id hss_sem2;
status_t app_initialize(char *config_path, char *log_path)
{
pid_t pid;
status_t rv;
int others = 0;
@ -34,32 +31,154 @@ status_t app_initialize(char *config_path, char *log_path)
d_trace_level(&_epc_main, others);
}
/************************* PGW Process **********************/
semaphore_create(&pgw_sem1, 0); /* copied to PGW/SGW/HSS process */
semaphore_create(&pgw_sem2, 0); /* copied to PGW/SGW/HSS process */
if (context_self()->hidden.disable_pgw == 0)
{
rv = proc_create(&pgw_proc, pgw_start_func, pgw_stop_func, NULL);
if (rv != CORE_OK) return rv;
pid = fork();
d_assert(pid >= 0, _exit(EXIT_FAILURE), "fork() failed");
if (pid == 0)
{
semaphore_post(pgw_sem1);
d_trace(1, "PGW try to initialize\n");
rv = pgw_initialize();
d_assert(rv == CORE_OK,, "Failed to intialize PGW");
d_trace(1, "PGW initialize...done\n");
semaphore_wait(pgw_sem2);
if (rv == CORE_OK)
{
d_trace(1, "PGW try to terminate\n");
pgw_terminate();
d_trace(1, "PGW terminate...done\n");
}
semaphore_post(pgw_sem1);
semaphore_delete(pgw_sem1); /* allocated from parent process */
semaphore_delete(pgw_sem2); /* allocated from parent process */
app_did_terminate();
core_terminate();
_exit(EXIT_SUCCESS);
}
semaphore_wait(pgw_sem1);
}
/************************* SGW Process **********************/
semaphore_create(&sgw_sem1, 0); /* copied to SGW/HSS process */
semaphore_create(&sgw_sem2, 0); /* copied to SGW/HSS process */
if (context_self()->hidden.disable_sgw == 0)
{
rv = proc_create(&sgw_proc, sgw_start_func, sgw_stop_func, NULL);
if (rv != CORE_OK) return rv;
pid = fork();
d_assert(pid >= 0, _exit(EXIT_FAILURE), "fork() failed");
if (pid == 0)
{
semaphore_delete(pgw_sem1); /* allocated from parent process */
semaphore_delete(pgw_sem2); /* allocated from parent process */
semaphore_post(sgw_sem1);
d_trace(1, "SGW try to initialize\n");
rv = sgw_initialize();
d_assert(rv == CORE_OK,, "Failed to intialize SGW");
d_trace(1, "SGW initialize...done\n");
semaphore_wait(sgw_sem2);
if (rv == CORE_OK)
{
d_trace(1, "SGW try to terminate\n");
sgw_terminate();
d_trace(1, "SGW terminate...done\n");
}
semaphore_post(sgw_sem1);
semaphore_delete(sgw_sem1); /* allocated from parent process */
semaphore_delete(sgw_sem2); /* allocated from parent process */
app_did_terminate();
core_terminate();
_exit(EXIT_SUCCESS);
}
semaphore_wait(sgw_sem1);
}
/************************* HSS Process **********************/
semaphore_create(&hss_sem1, 0); /* copied to HSS process */
semaphore_create(&hss_sem2, 0); /* copied to HSS process */
if (context_self()->hidden.disable_hss == 0)
{
rv = proc_create(&hss_proc, hss_start_func, hss_stop_func, NULL);
if (rv != CORE_OK) return rv;
pid = fork();
d_assert(pid >= 0, _exit(EXIT_FAILURE), "fork() failed");
if (pid == 0)
{
semaphore_delete(pgw_sem1); /* allocated from parent process */
semaphore_delete(pgw_sem2); /* allocated from parent process */
semaphore_delete(sgw_sem1); /* allocated from parent process */
semaphore_delete(sgw_sem2); /* allocated from parent process */
semaphore_post(hss_sem1);
d_trace(1, "HSS try to initialize\n");
rv = hss_initialize();
d_assert(rv == CORE_OK,, "Failed to intialize HSS");
d_trace(1, "HSS initialize...done\n");
semaphore_wait(hss_sem2);
if (rv == CORE_OK)
{
d_trace(1, "HSS try to terminate\n");
hss_terminate();
d_trace(1, "HSS terminate...done\n");
}
semaphore_post(hss_sem1);
semaphore_delete(hss_sem1); /* allocated from parent process */
semaphore_delete(hss_sem2); /* allocated from parent process */
app_did_terminate();
core_terminate();
_exit(EXIT_SUCCESS);
}
semaphore_wait(hss_sem1);
}
rv = app_did_initialize(config_path, log_path);
if (rv != CORE_OK) return rv;
d_trace(1, "MME try to initialize\n");
rv = mme_initialize();
d_assert(rv == CORE_OK, return rv, "Failed to intialize MME");
d_trace(1, "MME initialize...done\n");
rv = app_did_initialize(config_path, log_path);
if (rv != CORE_OK) return rv;
return CORE_OK;;
}
@ -71,75 +190,29 @@ void app_terminate(void)
mme_terminate();
d_trace(1, "MME terminate...done\n");
if (hss_proc)
proc_delete(hss_proc);
if (sgw_proc)
proc_delete(sgw_proc);
if (pgw_proc)
proc_delete(pgw_proc);
if (context_self()->hidden.disable_hss == 0)
{
semaphore_post(hss_sem2);
semaphore_wait(hss_sem1);
}
semaphore_delete(hss_sem1);
semaphore_delete(hss_sem2);
if (context_self()->hidden.disable_sgw == 0)
{
semaphore_post(sgw_sem2);
semaphore_wait(sgw_sem1);
}
semaphore_delete(sgw_sem1);
semaphore_delete(sgw_sem2);
if (context_self()->hidden.disable_pgw == 0)
{
semaphore_post(pgw_sem2);
semaphore_wait(pgw_sem1);
}
semaphore_delete(pgw_sem1);
semaphore_delete(pgw_sem2);
app_did_terminate();
}
static status_t PROC_FUNC pgw_start_func(proc_id id, void *data)
{
status_t rv;
d_trace(1, "PGW try to initialize\n");
rv = pgw_initialize();
d_assert(rv == CORE_OK, return rv, "Failed to intialize PGW");
d_trace(1, "PGW initialize...done\n");
return CORE_OK;
}
static status_t PROC_FUNC pgw_stop_func(proc_id id, void *data)
{
d_trace(1, "PGW try to terminate\n");
pgw_terminate();
d_trace(1, "PGW terminate...done\n");
return CORE_OK;
}
static status_t PROC_FUNC sgw_start_func(proc_id id, void *data)
{
status_t rv;
d_trace(1, "SGW try to initialize\n");
rv = sgw_initialize();
d_assert(rv == CORE_OK, return rv, "Failed to intialize SGW");
d_trace(1, "SGW initialize...done\n");
return CORE_OK;
}
static status_t PROC_FUNC sgw_stop_func(proc_id id, void *data)
{
d_trace(1, "SGW try to terminate\n");
sgw_terminate();
d_trace(1, "SGW terminate...done\n");
return CORE_OK;
}
static status_t PROC_FUNC hss_start_func(proc_id id, void *data)
{
status_t rv;
d_trace(1, "HSS try to initialize\n");
rv = hss_initialize();
d_assert(rv == CORE_OK, return rv, "Failed to intialize HSS");
d_trace(1, "HSS initialize...done\n");
return CORE_OK;
}
static status_t PROC_FUNC hss_stop_func(proc_id id, void *data)
{
d_trace(1, "HSS try to terminate\n");
hss_terminate();
d_trace(1, "HSS terminate...done\n");
return CORE_OK;
}

View File

@ -287,6 +287,11 @@ status_t hss_context_setup_trace_module()
if (s6a)
{
if (s6a <= 1) fd_g_debug_lvl = FD_LOG_ERROR;
else if (s6a <= 3) fd_g_debug_lvl = FD_LOG_NOTICE;
else if (s6a <= 5) fd_g_debug_lvl = FD_LOG_DEBUG;
else fd_g_debug_lvl = FD_LOG_ANNOYING;
extern int _hss_s6a_handler;
d_trace_level(&_hss_s6a_handler, s6a);
extern int _s6a_fd;

View File

@ -30,17 +30,6 @@ status_t app_will_initialize(char *config_path, char *log_path)
d_trace_level(&_app_init, others);
}
if (log_path)
context_self()->log_path = log_path;
if (context_self()->log_path)
{
d_print(" Logging '%s'\n", context_self()->log_path);
rv = thread_create(&logger_thread, NULL,
logger_main, context_self()->log_path);
if (rv != CORE_OK) return rv;
}
if (context_self()->db_uri)
{
rv = context_db_init(context_self()->db_uri);
@ -52,11 +41,29 @@ status_t app_will_initialize(char *config_path, char *log_path)
status_t app_did_initialize(char *config_path, char *log_path)
{
status_t rv;
if (log_path)
context_self()->log_path = log_path;
if (context_self()->log_path)
{
d_print(" Logging '%s'\n", context_self()->log_path);
rv = thread_create(&logger_thread, NULL,
logger_main, context_self()->log_path);
if (rv != CORE_OK) return rv;
}
return CORE_OK;
}
void app_will_terminate(void)
{
if (context_self()->log_path)
{
thread_delete(logger_thread);
}
}
void app_did_terminate(void)
@ -66,11 +73,6 @@ void app_did_terminate(void)
context_db_final();
}
if (context_self()->log_path)
{
thread_delete(logger_thread);
}
context_final();
}

View File

@ -34,7 +34,9 @@ status_t app_initialize(char *config_path, char *log_path)
void app_terminate(void)
{
printf("1\n");
app_will_terminate();
printf("2\n");
d_trace(1, "MME try to terminate\n");
mme_terminate();

View File

@ -826,6 +826,11 @@ status_t mme_context_setup_trace_module()
if (s6a)
{
if (s6a <= 1) fd_g_debug_lvl = FD_LOG_ERROR;
else if (s6a <= 3) fd_g_debug_lvl = FD_LOG_NOTICE;
else if (s6a <= 5) fd_g_debug_lvl = FD_LOG_DEBUG;
else fd_g_debug_lvl = FD_LOG_ANNOYING;
extern int _mme_s6a_handler;
d_trace_level(&_mme_s6a_handler, s6a);
extern int _s6a_fd;

27
support/README.md Normal file
View File

@ -0,0 +1,27 @@
* Network Configuration
user@host ~/Documents/git/nextepc/support$ \
sudo ./linux_netconfig.sh
* Generate Key & Cert for Diameter
user@host ~/Documents/git/nextepc/support$ \
./make_certs.sh ./freeDiameter
* Memory Leak Check
user@host ~/Documents/git/nextepc$ \
sudo valgrind --leak-check=full --show-leak-kinds=all \
--suppressions=support/valgrind/mongoc.suppressions \
--suppressions=support/valgrind/freeDiameter.suppressions \
./epcd
* Generate Suppression File
user@host ~/Documents/git/nextepc$ \
sudo valgrind --leak-check=full --show-reachable=yes --error-limit=no \
--gen-suppressions=all --log-file=support/valgrind/test.log \
./epcd
user@host ~/Documents/git/nextepc/support/valgrind$ \
sudo chown user:user test.log
user@host ~/Documents/git/nextepc/support/valgrind$ \
cat ./test.log | ./parse_suppressions.sh > test.supp

View File

@ -215,6 +215,23 @@
obj:/usr/lib/i386-linux-gnu/libgnutls.so.26.22.6
fun:gnutls_global_init
}
{
<insert_a_suppression_name_here>
Memcheck:Leak
match-leak-kinds: reachable
fun:calloc
obj:/usr/lib/i386-linux-gnu/libp11-kit.so.0.0.0
obj:/usr/lib/i386-linux-gnu/libp11-kit.so.0.0.0
fun:p11_kit_initialize_registered
fun:gnutls_pkcs11_init
fun:gnutls_global_init
fun:fd_core_initialize
fun:s6a_fd_init
fun:s6a_init
fun:hss_s6a_init
fun:hss_initialize
fun:app_initialize
}
{
<insert_a_suppression_name_here>
Memcheck:Leak
@ -232,3 +249,185 @@
obj:/usr/lib/i386-linux-gnu/libgnutls.so.26.22.6
fun:gnutls_global_init
}
{
<insert_a_suppression_name_here>
Memcheck:Leak
match-leak-kinds: reachable
fun:malloc
fun:strdup
fun:p11_kit_pin_register_callback
fun:gnutls_pkcs11_init
fun:gnutls_global_init
fun:fd_core_initialize
fun:s6a_fd_init
fun:s6a_init
fun:mme_s6a_init
fun:mme_initialize
fun:app_initialize
fun:main
}
{
<insert_a_suppression_name_here>
Memcheck:Leak
match-leak-kinds: reachable
fun:malloc
obj:/usr/lib/i386-linux-gnu/libgnutls.so.26.22.6
fun:gnutls_pkcs11_init
fun:gnutls_global_init
fun:fd_core_initialize
fun:s6a_fd_init
fun:s6a_init
fun:mme_s6a_init
fun:mme_initialize
fun:app_initialize
fun:main
}
{
<insert_a_suppression_name_here>
Memcheck:Leak
match-leak-kinds: reachable
fun:malloc
fun:strdup
fun:fd_log_threadname
fun:fd_core_initialize
fun:s6a_fd_init
fun:s6a_init
fun:mme_s6a_init
fun:mme_initialize
fun:app_initialize
fun:main
}
{
<insert_a_suppression_name_here>
Memcheck:Leak
match-leak-kinds: reachable
fun:calloc
fun:p11_kit_pin_register_callback
fun:gnutls_pkcs11_init
fun:gnutls_global_init
fun:fd_core_initialize
fun:s6a_fd_init
fun:s6a_init
fun:mme_s6a_init
fun:mme_initialize
fun:app_initialize
fun:main
}
{
<insert_a_suppression_name_here>
Memcheck:Leak
match-leak-kinds: reachable
fun:calloc
obj:/usr/lib/i386-linux-gnu/libp11-kit.so.0.0.0
fun:p11_kit_pin_register_callback
fun:gnutls_pkcs11_init
fun:gnutls_global_init
fun:fd_core_initialize
fun:s6a_fd_init
fun:s6a_init
fun:mme_s6a_init
fun:mme_initialize
fun:app_initialize
fun:main
}
{
<insert_a_suppression_name_here>
Memcheck:Leak
match-leak-kinds: reachable
fun:calloc
obj:/usr/lib/i386-linux-gnu/libp11-kit.so.0.0.0
obj:/usr/lib/i386-linux-gnu/libp11-kit.so.0.0.0
fun:p11_kit_pin_register_callback
fun:gnutls_pkcs11_init
fun:gnutls_global_init
fun:fd_core_initialize
fun:s6a_fd_init
fun:s6a_init
fun:mme_s6a_init
fun:mme_initialize
fun:app_initialize
}
{
<insert_a_suppression_name_here>
Memcheck:Leak
match-leak-kinds: reachable
fun:calloc
fun:_dlerror_run
fun:dlopen@@GLIBC_2.1
obj:/usr/lib/i386-linux-gnu/libp11-kit.so.0.0.0
obj:/usr/lib/i386-linux-gnu/libp11-kit.so.0.0.0
fun:p11_kit_initialize_registered
fun:gnutls_pkcs11_init
fun:gnutls_global_init
fun:fd_core_initialize
fun:s6a_fd_init
fun:s6a_init
fun:mme_s6a_init
}
{
<insert_a_suppression_name_here>
Memcheck:Leak
match-leak-kinds: reachable
fun:malloc
obj:/usr/lib/i386-linux-gnu/libgnutls.so.26.22.6
obj:/lib/i386-linux-gnu/libgcrypt.so.11.8.2
obj:/lib/i386-linux-gnu/libgcrypt.so.11.8.2
obj:/lib/i386-linux-gnu/libgcrypt.so.11.8.2
fun:gcry_check_version
obj:/usr/lib/i386-linux-gnu/libgnutls.so.26.22.6
fun:gnutls_global_init
fun:fd_core_initialize
fun:s6a_fd_init
fun:s6a_init
fun:mme_s6a_init
}
{
<insert_a_suppression_name_here>
Memcheck:Leak
match-leak-kinds: reachable
fun:malloc
obj:/usr/lib/i386-linux-gnu/libp11-kit.so.0.0.0
fun:p11_kit_pin_register_callback
fun:gnutls_pkcs11_init
fun:gnutls_global_init
fun:fd_core_initialize
fun:s6a_fd_init
fun:s6a_init
fun:mme_s6a_init
fun:mme_initialize
fun:app_initialize
fun:main
}
{
<insert_a_suppression_name_here>
Memcheck:Leak
match-leak-kinds: reachable
fun:malloc
fun:realloc
obj:/usr/lib/i386-linux-gnu/libp11-kit.so.0.0.0
obj:/usr/lib/i386-linux-gnu/libp11-kit.so.0.0.0
fun:p11_kit_pin_register_callback
fun:gnutls_pkcs11_init
fun:gnutls_global_init
fun:fd_core_initialize
fun:s6a_fd_init
fun:s6a_init
fun:mme_s6a_init
fun:mme_initialize
}
{
<insert_a_suppression_name_here>
Memcheck:Leak
match-leak-kinds: reachable
fun:malloc
fun:fd_dump_extend
obj:/usr/lib/libfdproto.so.1.2.0
obj:/usr/lib/libfdproto.so.1.2.0
fun:fd_hook_call
obj:/usr/lib/libfdcore.so.1.2.0
fun:fd_out_send
fun:fd_p_dp_initiate
obj:/usr/lib/libfdcore.so.1.2.0
fun:start_thread
fun:clone
}