]> git.proxmox.com Git - mirror_kronosnet.git/commitdiff
[dlopen] compress: fix load/unload of libraries and add extensive test
authorFabio M. Di Nitto <fdinitto@redhat.com>
Wed, 13 Sep 2017 12:43:53 +0000 (14:43 +0200)
committerFabio M. Di Nitto <fdinitto@redhat.com>
Thu, 14 Sep 2017 13:05:53 +0000 (15:05 +0200)
each handle should only unload libraries that has loaded or referenced
on exit, attempt to close all libraries from that handle
on compress_fini close only the one that's open

Signed-off-by: Fabio M. Di Nitto <fdinitto@redhat.com>
libknet/compress.c
libknet/compress.h
libknet/handle.c
libknet/internals.h
libknet/tests/Makefile.am
libknet/tests/int_lib_load_unload.c [new file with mode: 0644]

index 3babc61b492664b57d46f17538eb2870a72a7b61..12511789c248fed9bbbe8e2110292bed464f004c 100644 (file)
@@ -223,6 +223,7 @@ static int compress_load_lib(knet_handle_t knet_h, int cmp_model, int rate_limit
        }
 
        compress_modules_cmds[cmp_model].libref++;
+       knet_h->compress_activated[cmp_model] = 1;
 
        return 0;
 }
@@ -237,6 +238,7 @@ int compress_init(
                return -1;
        }
 
+       memset(knet_h->compress_activated, 0, KNET_MAX_COMPRESS_METHODS);
        memset(&last_load_failure, 0, sizeof(struct timespec));
 
        return 0;
@@ -310,6 +312,9 @@ int compress_cfg(
                                err = -1;
                                goto out_unlock;
                        }
+               } else {
+                       compress_modules_cmds[cmp_model].libref++;
+                       knet_h->compress_activated[cmp_model] = 1;
                }
 
                if (val_level(knet_h, cmp_model, knet_handle_compress_cfg->compress_level) < 0) {
@@ -327,6 +332,8 @@ out_unlock:
        if (!err) {
                knet_h->compress_model = cmp_model;
                knet_h->compress_level = knet_handle_compress_cfg->compress_level;
+       } else {
+               knet_h->compress_model = 0;
        }
 
        errno = savederrno;
@@ -334,7 +341,8 @@ out_unlock:
 }
 
 void compress_fini(
-       knet_handle_t knet_h)
+       knet_handle_t knet_h,
+       int all)
 {
        int savederrno = 0;
        int idx = 0;
@@ -349,19 +357,24 @@ void compress_fini(
        while (compress_modules_cmds[idx].model_name != NULL) {
                if ((compress_modules_cmds[idx].built_in == 1) &&
                    (compress_modules_cmds[idx].loaded == 1) &&
+                   (compress_modules_cmds[idx].model_id > 0) &&
+                   (knet_h->compress_activated[compress_modules_cmds[idx].model_id] == 1) &&
                    (idx < KNET_MAX_COMPRESS_METHODS)) {
-                       if (compress_modules_cmds[idx].fini != NULL) {
-                               compress_modules_cmds[idx].fini(knet_h, idx);
-                       } else {
-                               knet_h->compress_int_data[idx] = NULL;
-                       }
-                       compress_modules_cmds[idx].libref--;
-
-                       if ((compress_modules_cmds[idx].libref == 0) &&
-                           (compress_modules_cmds[idx].loaded == 1)) {
-                               log_debug(knet_h, KNET_SUB_COMPRESS, "Unloading %s library", compress_modules_cmds[idx].model_name);
-                               compress_modules_cmds[idx].unload_lib(knet_h);
-                               compress_modules_cmds[idx].loaded = 0;
+                       if ((all) || (compress_modules_cmds[idx].model_id == knet_h->compress_model)) {
+                               if (compress_modules_cmds[idx].fini != NULL) {
+                                       compress_modules_cmds[idx].fini(knet_h, idx);
+                               } else {
+                                       knet_h->compress_int_data[idx] = NULL;
+                               }
+                               compress_modules_cmds[idx].libref--;
+                               knet_h->compress_activated[compress_modules_cmds[idx].model_id] = 0;
+
+                               if ((compress_modules_cmds[idx].libref == 0) &&
+                                   (compress_modules_cmds[idx].loaded == 1)) {
+                                       log_debug(knet_h, KNET_SUB_COMPRESS, "Unloading %s library", compress_modules_cmds[idx].model_name);
+                                       compress_modules_cmds[idx].unload_lib(knet_h);
+                                       compress_modules_cmds[idx].loaded = 0;
+                               }
                        }
                }
                idx++;
@@ -436,6 +449,11 @@ int decompress(
                                strerror(savederrno));
                        goto out_unlock;
                }
+       } else {
+               if (!knet_h->compress_activated[compress_model]) {
+                       compress_modules_cmds[compress_model].libref++;
+                       knet_h->compress_activated[compress_model] = 1;
+               }
        }
 
        err = compress_modules_cmds[compress_model].decompress(knet_h, buf_in, buf_in_len, buf_out, buf_out_len);
index fd15b3e55b6a284f24133bfb737eaca240bc6847..9ba85c99bee80cd9a2711e2b490675faac87abdb 100644 (file)
@@ -107,7 +107,8 @@ int compress_init(
        knet_handle_t knet_h);
 
 void compress_fini(
-       knet_handle_t knet_h);
+       knet_handle_t knet_h,
+       int all);
 
 int compress(
        knet_handle_t knet_h,
index 655b92faff3e11d11c529ccb9ab33f7be2ac06ea..71de5708891217d30b3742b0542dc7b134857732 100644 (file)
@@ -775,7 +775,7 @@ int knet_handle_free(knet_handle_t knet_h)
        _destroy_buffers(knet_h);
        _close_socks(knet_h);
        crypto_fini(knet_h);
-       compress_fini(knet_h);
+       compress_fini(knet_h, 1);
        _destroy_locks(knet_h);
 
 exit_nolock:
@@ -1405,7 +1405,7 @@ int knet_handle_compress(knet_handle_t knet_h, struct knet_handle_compress_cfg *
                return -1;
        }
 
-       compress_fini(knet_h);
+       compress_fini(knet_h, 0);
        err = compress_cfg(knet_h, knet_handle_compress_cfg);
        savederrno = errno;
 
index 22e6b8bdf2394afe76b158c2a9dcac5435325dd2..af99b1a22c8d20c2444112dbb4a612f152746e3b 100644 (file)
@@ -190,6 +190,7 @@ struct knet_handle {
        int compress_level;
        uint32_t compress_threshold;
        void *compress_int_data[KNET_MAX_COMPRESS_METHODS]; /* for compress method private data */
+       uint8_t compress_activated[KNET_MAX_COMPRESS_METHODS]; /* track active compression library used by this handle */
        unsigned char *recv_from_links_buf_decompress;
        unsigned char *send_to_links_buf_compress;
        seq_num_t tx_seq_num;
index 59490c83c03272c6ad1314216edd8f93a398ec25..5adc6b7e01879e96ddb319e040e0bcb00e7717ed 100644 (file)
@@ -33,6 +33,7 @@ check_PROGRAMS                = \
                          $(fun_checks)
 
 int_checks             = \
+                         int_lib_load_unload \
                          int_crypto_test \
                          int_timediff_test
 
@@ -61,6 +62,9 @@ check-api-test-coverage:
 
 pckt_test_SOURCES      = pckt_test.c
 
+int_lib_load_unload_SOURCES = int_lib_load_unload.c \
+                             test-common.c
+
 int_crypto_test_SOURCES = int_crypto.c \
                          ../common.c \
                          ../crypto.c \
diff --git a/libknet/tests/int_lib_load_unload.c b/libknet/tests/int_lib_load_unload.c
new file mode 100644 (file)
index 0000000..33fc540
--- /dev/null
@@ -0,0 +1,791 @@
+#include "config.h"
+
+#include <link.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <errno.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <fcntl.h>
+#include <pthread.h>
+
+#include "libknet.h"
+#include "test-common.h"
+
+char *orig[256];
+int orig_idx = 0;
+
+char *cur[256];
+int cur_idx = 0;
+
+int use_cur = 0;
+
+static int callback(struct dl_phdr_info *info, size_t size, void *data)
+{
+       if (strlen(info->dlpi_name) > 0) {
+               if (use_cur) {
+                       cur[cur_idx] = strdup(info->dlpi_name);
+                       cur_idx++;
+               } else {
+                       orig[orig_idx] = strdup(info->dlpi_name);
+                       orig_idx++;
+               }
+       }
+
+       return 0;
+}
+
+static void free_loop(void)
+{
+       int i;
+
+       if (use_cur) {
+               for (i = 0; i < cur_idx; i++) {
+                       free(cur[i]);
+                       cur[i] = NULL;
+               }
+               cur_idx = 0;
+       } else {
+               for (i = 0; i < orig_idx; i++) {
+                       free(orig[i]);
+                       orig[i] = NULL;
+               }
+               orig_idx = 0;
+       }
+}
+
+static int find_lib(const char *libname)
+{
+       int i;
+
+       for (i = 0; i < cur_idx; i++) {
+               if (strstr(cur[i], libname) != NULL) {
+                       return 1;
+               }
+       }
+       return 0;
+}
+
+static void test(void)
+{
+       int logfds[2];
+       knet_handle_t knet_h1, knet_h2;
+       struct knet_handle_crypto_cfg knet_handle_crypto_cfg;
+       struct knet_handle_compress_cfg knet_handle_compress_cfg;
+       int do_close = 0;
+
+       use_cur = 0;
+       dl_iterate_phdr(callback, NULL);
+       use_cur = 1;
+
+       setup_logpipes(logfds);
+
+       knet_h1 = knet_handle_new(1, logfds[1], KNET_LOG_DEBUG);
+       if (!knet_h1) {
+               printf("knet_handle_new failed: %s\n", strerror(errno));
+               flush_logs(logfds[0], stdout);
+               close_logpipes(logfds);
+               exit(FAIL);
+       }
+       flush_logs(logfds[0], stdout);
+
+#ifdef BUILDCRYPTONSS
+       printf("Testing loading crypto library\n");
+
+       memset(&knet_handle_crypto_cfg, 0, sizeof(struct knet_handle_crypto_cfg));
+       strncpy(knet_handle_crypto_cfg.crypto_model, "nss", sizeof(knet_handle_crypto_cfg.crypto_model) - 1);
+       strncpy(knet_handle_crypto_cfg.crypto_cipher_type, "aes128", sizeof(knet_handle_crypto_cfg.crypto_cipher_type) - 1);
+       strncpy(knet_handle_crypto_cfg.crypto_hash_type, "sha1", sizeof(knet_handle_crypto_cfg.crypto_hash_type) - 1);
+       knet_handle_crypto_cfg.private_key_len = 2000;
+
+       if (knet_handle_crypto(knet_h1, &knet_handle_crypto_cfg)) {
+               printf("knet_handle_crypto failed with correct config: %s\n", strerror(errno));
+               knet_handle_free(knet_h1);
+               flush_logs(logfds[0], stdout);
+               close_logpipes(logfds);
+               exit(FAIL);
+       }
+       flush_logs(logfds[0], stdout);
+
+       dl_iterate_phdr(callback, NULL);
+
+       if (cur_idx <= orig_idx) {
+               printf("Error loading library\n");
+               knet_handle_free(knet_h1);
+               flush_logs(logfds[0], stdout);
+               close_logpipes(logfds);
+               exit(FAIL);
+       }
+
+       if (!find_lib("libnss")) {
+               printf("library doesn't appear to be loaded\n");
+               knet_handle_free(knet_h1);
+               flush_logs(logfds[0], stdout);
+               close_logpipes(logfds);
+               exit(FAIL);
+       }
+
+       free_loop();
+
+       printf("Testing unloading crypto library\n");
+
+       memset(&knet_handle_crypto_cfg, 0, sizeof(struct knet_handle_crypto_cfg));
+       strncpy(knet_handle_crypto_cfg.crypto_model, "none", sizeof(knet_handle_crypto_cfg.crypto_model) - 1);
+       strncpy(knet_handle_crypto_cfg.crypto_cipher_type, "none", sizeof(knet_handle_crypto_cfg.crypto_cipher_type) - 1);
+       strncpy(knet_handle_crypto_cfg.crypto_hash_type, "none", sizeof(knet_handle_crypto_cfg.crypto_hash_type) - 1);
+       knet_handle_crypto_cfg.private_key_len = 2000;
+
+       if (knet_handle_crypto(knet_h1, &knet_handle_crypto_cfg)) {
+               printf("knet_handle_crypto failed with correct config: %s\n", strerror(errno));
+               knet_handle_free(knet_h1);
+               flush_logs(logfds[0], stdout);
+               close_logpipes(logfds);
+               exit(FAIL);
+       }
+       flush_logs(logfds[0], stdout);
+
+       dl_iterate_phdr(callback, NULL);
+
+       if (cur_idx != orig_idx) {
+               printf("Error unloading library\n");
+               knet_handle_free(knet_h1);
+               flush_logs(logfds[0], stdout);
+               close_logpipes(logfds);
+               exit(FAIL);
+       }
+
+       if (find_lib("libnss")) {
+               printf("library doesn't appear to be unloaded\n");
+               knet_handle_free(knet_h1);
+               flush_logs(logfds[0], stdout);
+               close_logpipes(logfds);
+               exit(FAIL);
+       }
+
+       free_loop();
+#else
+       printf("WARNING: nss support not builtin the library. Unable to test/verify internal crypto load/unload code\n");
+#endif
+
+#ifdef BUILDCOMPZLIB
+       printf("Testing loading compress library\n");
+
+       memset(&knet_handle_compress_cfg, 0, sizeof(struct knet_handle_compress_cfg));
+       strncpy(knet_handle_compress_cfg.compress_model, "zlib", sizeof(knet_handle_compress_cfg.compress_model) - 1);
+       knet_handle_compress_cfg.compress_level = 1;
+       knet_handle_compress_cfg.compress_threshold = 64;
+
+       if (knet_handle_compress(knet_h1, &knet_handle_compress_cfg) != 0) {
+               printf("knet_handle_compress failed with correct config: %s\n", strerror(errno));
+               knet_handle_free(knet_h1);
+               flush_logs(logfds[0], stdout);
+               close_logpipes(logfds);
+               exit(FAIL);
+       }
+       flush_logs(logfds[0], stdout);
+
+       dl_iterate_phdr(callback, NULL);
+
+       if (cur_idx <= orig_idx) {
+               printf("Error loading library\n");
+               knet_handle_free(knet_h1);
+               flush_logs(logfds[0], stdout);
+               close_logpipes(logfds);
+               exit(FAIL);
+       }
+
+       if (!find_lib("libz")) {
+               printf("library doesn't appear to be loaded\n");
+               knet_handle_free(knet_h1);
+               flush_logs(logfds[0], stdout);
+               close_logpipes(logfds);
+               exit(FAIL);
+       }
+
+       free_loop();
+
+       printf("Testing unloading compress library\n");
+
+       memset(&knet_handle_compress_cfg, 0, sizeof(struct knet_handle_compress_cfg));
+       strncpy(knet_handle_compress_cfg.compress_model, "none", sizeof(knet_handle_compress_cfg.compress_model) - 1);
+       knet_handle_compress_cfg.compress_level = 1;
+       knet_handle_compress_cfg.compress_threshold = 64;
+
+       if (knet_handle_compress(knet_h1, &knet_handle_compress_cfg) != 0) {
+               printf("knet_handle_compress failed with correct config: %s\n", strerror(errno));
+               knet_handle_free(knet_h1);
+               flush_logs(logfds[0], stdout);
+               close_logpipes(logfds);
+               exit(FAIL);
+       }
+       flush_logs(logfds[0], stdout);
+
+       dl_iterate_phdr(callback, NULL);
+
+       if (cur_idx != orig_idx) {
+               printf("Error unloading library\n");
+               knet_handle_free(knet_h1);
+               flush_logs(logfds[0], stdout);
+               close_logpipes(logfds);
+               exit(FAIL);
+       }
+
+       if (find_lib("libz")) {
+               printf("library doesn't appear to be unloaded\n");
+               knet_handle_free(knet_h1);
+               flush_logs(logfds[0], stdout);
+               close_logpipes(logfds);
+               exit(FAIL);
+       }
+
+       free_loop();
+#else
+       printf("WARNING: zlib support not builtin the library. Unable to test/verify internal compress load/unload code\n");
+#endif
+
+       knet_h2 = knet_handle_new(1, logfds[1], KNET_LOG_DEBUG);
+       if (!knet_h2) {
+               printf("knet_handle_new failed: %s\n", strerror(errno));
+               knet_handle_free(knet_h1);
+               flush_logs(logfds[0], stdout);
+               close_logpipes(logfds);
+               exit(FAIL);
+       }
+       flush_logs(logfds[0], stdout);
+
+#ifdef BUILDCRYPTONSS
+       printf("Testing multiple handles loading crypto library\n");
+
+       memset(&knet_handle_crypto_cfg, 0, sizeof(struct knet_handle_crypto_cfg));
+       strncpy(knet_handle_crypto_cfg.crypto_model, "nss", sizeof(knet_handle_crypto_cfg.crypto_model) - 1);
+       strncpy(knet_handle_crypto_cfg.crypto_cipher_type, "aes128", sizeof(knet_handle_crypto_cfg.crypto_cipher_type) - 1);
+       strncpy(knet_handle_crypto_cfg.crypto_hash_type, "sha1", sizeof(knet_handle_crypto_cfg.crypto_hash_type) - 1);
+       knet_handle_crypto_cfg.private_key_len = 2000;
+
+       if (knet_handle_crypto(knet_h1, &knet_handle_crypto_cfg)) {
+               printf("knet_handle_crypto failed with correct config: %s\n", strerror(errno));
+               knet_handle_free(knet_h1);
+               knet_handle_free(knet_h2);
+               flush_logs(logfds[0], stdout);
+               close_logpipes(logfds);
+               exit(FAIL);
+       }
+       flush_logs(logfds[0], stdout);
+
+       if (knet_handle_crypto(knet_h2, &knet_handle_crypto_cfg)) {
+               printf("knet_handle_crypto failed with correct config: %s\n", strerror(errno));
+               knet_handle_free(knet_h1);
+               knet_handle_free(knet_h2);
+               flush_logs(logfds[0], stdout);
+               close_logpipes(logfds);
+               exit(FAIL);
+       }
+       flush_logs(logfds[0], stdout);
+
+       dl_iterate_phdr(callback, NULL);
+
+       if (cur_idx <= orig_idx) {
+               printf("Error loading library\n");
+               knet_handle_free(knet_h1);
+               knet_handle_free(knet_h2);
+               flush_logs(logfds[0], stdout);
+               close_logpipes(logfds);
+               exit(FAIL);
+       }
+
+       if (!find_lib("libnss")) {
+               printf("library doesn't appear to be loaded\n");
+               knet_handle_free(knet_h1);
+               knet_handle_free(knet_h2);
+               flush_logs(logfds[0], stdout);
+               close_logpipes(logfds);
+               exit(FAIL);
+       }
+
+       free_loop();
+
+       printf("Testing multiple handles unloading crypto library\n");
+
+       memset(&knet_handle_crypto_cfg, 0, sizeof(struct knet_handle_crypto_cfg));
+       strncpy(knet_handle_crypto_cfg.crypto_model, "none", sizeof(knet_handle_crypto_cfg.crypto_model) - 1);
+       strncpy(knet_handle_crypto_cfg.crypto_cipher_type, "none", sizeof(knet_handle_crypto_cfg.crypto_cipher_type) - 1);
+       strncpy(knet_handle_crypto_cfg.crypto_hash_type, "none", sizeof(knet_handle_crypto_cfg.crypto_hash_type) - 1);
+       knet_handle_crypto_cfg.private_key_len = 2000;
+
+       if (knet_handle_crypto(knet_h1, &knet_handle_crypto_cfg)) {
+               printf("knet_handle_crypto failed with correct config: %s\n", strerror(errno));
+               knet_handle_free(knet_h1);
+               knet_handle_free(knet_h2);
+               flush_logs(logfds[0], stdout);
+               close_logpipes(logfds);
+               exit(FAIL);
+       }
+       flush_logs(logfds[0], stdout);
+
+       dl_iterate_phdr(callback, NULL);
+
+       if (cur_idx <= orig_idx) {
+               printf("Error library has been unloaded prematurely\n");
+               knet_handle_free(knet_h1);
+               knet_handle_free(knet_h2);
+               flush_logs(logfds[0], stdout);
+               close_logpipes(logfds);
+               exit(FAIL);
+       }
+
+       if (!find_lib("libnss")) {
+               printf("library doesn't appear to be loaded\n");
+               knet_handle_free(knet_h1);
+               knet_handle_free(knet_h2);
+               flush_logs(logfds[0], stdout);
+               close_logpipes(logfds);
+               exit(FAIL);
+       }
+
+       free_loop();
+
+       if (knet_handle_crypto(knet_h2, &knet_handle_crypto_cfg)) {
+               printf("knet_handle_crypto failed with correct config: %s\n", strerror(errno));
+               knet_handle_free(knet_h1);
+               knet_handle_free(knet_h2);
+               flush_logs(logfds[0], stdout);
+               close_logpipes(logfds);
+               exit(FAIL);
+       }
+       flush_logs(logfds[0], stdout);
+
+       dl_iterate_phdr(callback, NULL);
+
+       if (cur_idx != orig_idx) {
+               printf("Error unloading library\n");
+               knet_handle_free(knet_h1);
+               knet_handle_free(knet_h2);
+               flush_logs(logfds[0], stdout);
+               close_logpipes(logfds);
+               exit(FAIL);
+       }
+
+       if (find_lib("libnss")) {
+               printf("library doesn't appear to be unloaded\n");
+               knet_handle_free(knet_h1);
+               knet_handle_free(knet_h2);
+               flush_logs(logfds[0], stdout);
+               close_logpipes(logfds);
+               exit(FAIL);
+       }
+
+       free_loop();
+#else
+       printf("WARNING: nss support not builtin the library. Unable to test/verify internal crypto load/unload code\n");
+#endif
+
+#ifdef BUILDCOMPZLIB
+       printf("Testing multiple handles loading compress library\n");
+
+       memset(&knet_handle_compress_cfg, 0, sizeof(struct knet_handle_compress_cfg));
+       strncpy(knet_handle_compress_cfg.compress_model, "zlib", sizeof(knet_handle_compress_cfg.compress_model) - 1);
+       knet_handle_compress_cfg.compress_level = 1;
+       knet_handle_compress_cfg.compress_threshold = 64;
+
+       if (knet_handle_compress(knet_h1, &knet_handle_compress_cfg) != 0) {
+               printf("knet_handle_compress failed with correct config: %s\n", strerror(errno));
+               knet_handle_free(knet_h1);
+               knet_handle_free(knet_h2);
+               flush_logs(logfds[0], stdout);
+               close_logpipes(logfds);
+               exit(FAIL);
+       }
+       flush_logs(logfds[0], stdout);
+
+       if (knet_handle_compress(knet_h2, &knet_handle_compress_cfg) != 0) {
+               printf("knet_handle_compress failed with correct config: %s\n", strerror(errno));
+               knet_handle_free(knet_h1);
+               knet_handle_free(knet_h2);
+               flush_logs(logfds[0], stdout);
+               close_logpipes(logfds);
+               exit(FAIL);
+       }
+       flush_logs(logfds[0], stdout);
+
+       dl_iterate_phdr(callback, NULL);
+
+       if (cur_idx <= orig_idx) {
+               printf("Error loading library\n");
+               knet_handle_free(knet_h1);
+               knet_handle_free(knet_h2);
+               flush_logs(logfds[0], stdout);
+               close_logpipes(logfds);
+               exit(FAIL);
+       }
+
+       if (!find_lib("libz")) {
+               printf("library doesn't appear to be loaded\n");
+               knet_handle_free(knet_h1);
+               knet_handle_free(knet_h2);
+               flush_logs(logfds[0], stdout);
+               close_logpipes(logfds);
+               exit(FAIL);
+       }
+
+       free_loop();
+
+       printf("Testing multiple handles unloading compress library\n");
+
+       memset(&knet_handle_compress_cfg, 0, sizeof(struct knet_handle_compress_cfg));
+       strncpy(knet_handle_compress_cfg.compress_model, "none", sizeof(knet_handle_compress_cfg.compress_model) - 1);
+       knet_handle_compress_cfg.compress_level = 1;
+       knet_handle_compress_cfg.compress_threshold = 64;
+
+       if (knet_handle_compress(knet_h1, &knet_handle_compress_cfg) != 0) {
+               printf("knet_handle_compress failed with correct config: %s\n", strerror(errno));
+               knet_handle_free(knet_h1);
+               knet_handle_free(knet_h2);
+               flush_logs(logfds[0], stdout);
+               close_logpipes(logfds);
+               exit(FAIL);
+       }
+       flush_logs(logfds[0], stdout);
+
+       dl_iterate_phdr(callback, NULL);
+
+       if (cur_idx <= orig_idx) {
+               printf("Error library has been unloaded prematurely\n");
+               knet_handle_free(knet_h1);
+               knet_handle_free(knet_h2);
+               flush_logs(logfds[0], stdout);
+               close_logpipes(logfds);
+               exit(FAIL);
+       }
+
+       if (!find_lib("libz")) {
+               printf("library doesn't appear to be loaded\n");
+               knet_handle_free(knet_h1);
+               knet_handle_free(knet_h2);
+               flush_logs(logfds[0], stdout);
+               close_logpipes(logfds);
+               exit(FAIL);
+       }
+
+       free_loop();
+
+       if (knet_handle_compress(knet_h2, &knet_handle_compress_cfg) != 0) {
+               printf("knet_handle_compress failed with correct config: %s\n", strerror(errno));
+               knet_handle_free(knet_h1);
+               knet_handle_free(knet_h2);
+               flush_logs(logfds[0], stdout);
+               close_logpipes(logfds);
+               exit(FAIL);
+       }
+       flush_logs(logfds[0], stdout);
+
+       dl_iterate_phdr(callback, NULL);
+
+       if (cur_idx != orig_idx) {
+               printf("Error unloading library\n");
+               knet_handle_free(knet_h1);
+               knet_handle_free(knet_h2);
+               flush_logs(logfds[0], stdout);
+               close_logpipes(logfds);
+               exit(FAIL);
+       }
+
+       if (find_lib("libz")) {
+               printf("library doesn't appear to be unloaded\n");
+               knet_handle_free(knet_h1);
+               knet_handle_free(knet_h2);
+               flush_logs(logfds[0], stdout);
+               close_logpipes(logfds);
+               exit(FAIL);
+       }
+
+       free_loop();
+#else
+       printf("WARNING: zlib support not builtin the library. Unable to test/verify internal compress load/unload code\n");
+#endif
+
+#ifdef BUILDCOMPZLIB
+#ifdef BUILDCOMPBZIP2
+       printf("Testing multiple handles loading different compress libraries\n");
+
+       memset(&knet_handle_compress_cfg, 0, sizeof(struct knet_handle_compress_cfg));
+       strncpy(knet_handle_compress_cfg.compress_model, "zlib", sizeof(knet_handle_compress_cfg.compress_model) - 1);
+       knet_handle_compress_cfg.compress_level = 1;
+       knet_handle_compress_cfg.compress_threshold = 64;
+
+       if (knet_handle_compress(knet_h1, &knet_handle_compress_cfg) != 0) {
+               printf("knet_handle_compress failed with correct config: %s\n", strerror(errno));
+               knet_handle_free(knet_h1);
+               knet_handle_free(knet_h2);
+               flush_logs(logfds[0], stdout);
+               close_logpipes(logfds);
+               exit(FAIL);
+       }
+       flush_logs(logfds[0], stdout);
+
+       memset(&knet_handle_compress_cfg, 0, sizeof(struct knet_handle_compress_cfg));
+       strncpy(knet_handle_compress_cfg.compress_model, "bzip2", sizeof(knet_handle_compress_cfg.compress_model) - 1);
+       knet_handle_compress_cfg.compress_level = 1;
+       knet_handle_compress_cfg.compress_threshold = 64;
+
+       if (knet_handle_compress(knet_h2, &knet_handle_compress_cfg) != 0) {
+               printf("knet_handle_compress failed with correct config: %s\n", strerror(errno));
+               knet_handle_free(knet_h1);
+               knet_handle_free(knet_h2);
+               flush_logs(logfds[0], stdout);
+               close_logpipes(logfds);
+               exit(FAIL);
+       }
+       flush_logs(logfds[0], stdout);
+
+       dl_iterate_phdr(callback, NULL);
+
+       if (cur_idx <= orig_idx) {
+               printf("Error loading library\n");
+               knet_handle_free(knet_h1);
+               knet_handle_free(knet_h2);
+               flush_logs(logfds[0], stdout);
+               close_logpipes(logfds);
+               exit(FAIL);
+       }
+
+       if (!find_lib("libz")) {
+               printf("library doesn't appear to be loaded\n");
+               knet_handle_free(knet_h1);
+               knet_handle_free(knet_h2);
+               flush_logs(logfds[0], stdout);
+               close_logpipes(logfds);
+               exit(FAIL);
+       }
+
+       if (!find_lib("libbz2")) {
+               printf("library doesn't appear to be loaded\n");
+               knet_handle_free(knet_h1);
+               knet_handle_free(knet_h2);
+               flush_logs(logfds[0], stdout);
+               close_logpipes(logfds);
+               exit(FAIL);
+       }
+
+       free_loop();
+
+       printf("Testing multiple handles unloading compress library\n");
+
+       memset(&knet_handle_compress_cfg, 0, sizeof(struct knet_handle_compress_cfg));
+       strncpy(knet_handle_compress_cfg.compress_model, "none", sizeof(knet_handle_compress_cfg.compress_model) - 1);
+       knet_handle_compress_cfg.compress_level = 1;
+       knet_handle_compress_cfg.compress_threshold = 64;
+
+       if (knet_handle_compress(knet_h1, &knet_handle_compress_cfg) != 0) {
+               printf("knet_handle_compress failed with correct config: %s\n", strerror(errno));
+               knet_handle_free(knet_h1);
+               knet_handle_free(knet_h2);
+               flush_logs(logfds[0], stdout);
+               close_logpipes(logfds);
+               exit(FAIL);
+       }
+       flush_logs(logfds[0], stdout);
+
+       dl_iterate_phdr(callback, NULL);
+
+       if (cur_idx <= orig_idx) {
+               printf("Error library has been unloaded prematurely\n");
+               knet_handle_free(knet_h1);
+               knet_handle_free(knet_h2);
+               flush_logs(logfds[0], stdout);
+               close_logpipes(logfds);
+               exit(FAIL);
+       }
+
+       if (find_lib("libz")) {
+               printf("library doesn't appear to be unloaded\n");
+               knet_handle_free(knet_h1);
+               knet_handle_free(knet_h2);
+               flush_logs(logfds[0], stdout);
+               close_logpipes(logfds);
+               exit(FAIL);
+       }
+
+       free_loop();
+
+       if (knet_handle_compress(knet_h2, &knet_handle_compress_cfg) != 0) {
+               printf("knet_handle_compress failed with correct config: %s\n", strerror(errno));
+               knet_handle_free(knet_h1);
+               knet_handle_free(knet_h2);
+               flush_logs(logfds[0], stdout);
+               close_logpipes(logfds);
+               exit(FAIL);
+       }
+       flush_logs(logfds[0], stdout);
+
+       dl_iterate_phdr(callback, NULL);
+
+       if (cur_idx != orig_idx) {
+               printf("Error unloading library\n");
+               knet_handle_free(knet_h1);
+               knet_handle_free(knet_h2);
+               flush_logs(logfds[0], stdout);
+               close_logpipes(logfds);
+               exit(FAIL);
+       }
+
+       if (find_lib("libbz2")) {
+               printf("library doesn't appear to be unloaded\n");
+               knet_handle_free(knet_h1);
+               knet_handle_free(knet_h2);
+               flush_logs(logfds[0], stdout);
+               close_logpipes(logfds);
+               exit(FAIL);
+       }
+
+       free_loop();
+#else
+       printf("WARNING: bzip2 support not builtin the library. Unable to test/verify internal compress load/unload code\n");
+#endif
+#else
+       printf("WARNING: zlib support not builtin the library. Unable to test/verify internal compress load/unload code\n");
+#endif
+
+#ifdef BUILDCOMPZLIB
+#ifdef BUILDCOMPBZIP2
+       printf("Testing multiple handles loading different compress libraries (part 2)\n");
+
+       memset(&knet_handle_compress_cfg, 0, sizeof(struct knet_handle_compress_cfg));
+       strncpy(knet_handle_compress_cfg.compress_model, "zlib", sizeof(knet_handle_compress_cfg.compress_model) - 1);
+       knet_handle_compress_cfg.compress_level = 1;
+       knet_handle_compress_cfg.compress_threshold = 64;
+
+       if (knet_handle_compress(knet_h1, &knet_handle_compress_cfg) != 0) {
+               printf("knet_handle_compress failed with correct config: %s\n", strerror(errno));
+               knet_handle_free(knet_h1);
+               knet_handle_free(knet_h2);
+               flush_logs(logfds[0], stdout);
+               close_logpipes(logfds);
+               exit(FAIL);
+       }
+       flush_logs(logfds[0], stdout);
+
+       memset(&knet_handle_compress_cfg, 0, sizeof(struct knet_handle_compress_cfg));
+       strncpy(knet_handle_compress_cfg.compress_model, "bzip2", sizeof(knet_handle_compress_cfg.compress_model) - 1);
+       knet_handle_compress_cfg.compress_level = 1;
+       knet_handle_compress_cfg.compress_threshold = 64;
+
+       if (knet_handle_compress(knet_h2, &knet_handle_compress_cfg) != 0) {
+               printf("knet_handle_compress failed with correct config: %s\n", strerror(errno));
+               knet_handle_free(knet_h1);
+               knet_handle_free(knet_h2);
+               flush_logs(logfds[0], stdout);
+               close_logpipes(logfds);
+               exit(FAIL);
+       }
+       flush_logs(logfds[0], stdout);
+
+       dl_iterate_phdr(callback, NULL);
+
+       if (cur_idx <= orig_idx) {
+               printf("Error loading library\n");
+               knet_handle_free(knet_h1);
+               knet_handle_free(knet_h2);
+               flush_logs(logfds[0], stdout);
+               close_logpipes(logfds);
+               exit(FAIL);
+       }
+
+       if (!find_lib("libz")) {
+               printf("library doesn't appear to be loaded\n");
+               knet_handle_free(knet_h1);
+               knet_handle_free(knet_h2);
+               flush_logs(logfds[0], stdout);
+               close_logpipes(logfds);
+               exit(FAIL);
+       }
+
+       if (!find_lib("libbz2")) {
+               printf("library doesn't appear to be loaded\n");
+               knet_handle_free(knet_h1);
+               knet_handle_free(knet_h2);
+               flush_logs(logfds[0], stdout);
+               close_logpipes(logfds);
+               exit(FAIL);
+       }
+
+       free_loop();
+
+       printf("Testing multiple handles unloading compress library by closing handles\n");
+
+       knet_handle_free(knet_h1);
+       flush_logs(logfds[0], stdout);
+
+       dl_iterate_phdr(callback, NULL);
+
+       if (cur_idx <= orig_idx) {
+               printf("Error library has been unloaded prematurely\n");
+               knet_handle_free(knet_h2);
+               flush_logs(logfds[0], stdout);
+               close_logpipes(logfds);
+               exit(FAIL);
+       }
+
+       if (find_lib("libz")) {
+               printf("library doesn't appear to be unloaded\n");
+               knet_handle_free(knet_h2);
+               flush_logs(logfds[0], stdout);
+               close_logpipes(logfds);
+               exit(FAIL);
+       }
+
+       free_loop();
+
+       knet_handle_free(knet_h2);
+       flush_logs(logfds[0], stdout);
+
+       dl_iterate_phdr(callback, NULL);
+
+       /*
+        * something is pulling in libgcc and we need to account for it
+        */
+       if (cur_idx != orig_idx + 1) {
+               printf("Error unloading library\n");
+               flush_logs(logfds[0], stdout);
+               close_logpipes(logfds);
+               exit(FAIL);
+       }
+
+       if (find_lib("libbz2")) {
+               printf("library doesn't appear to be unloaded\n");
+               flush_logs(logfds[0], stdout);
+               close_logpipes(logfds);
+               exit(FAIL);
+       }
+
+       free_loop();
+#else
+       printf("WARNING: bzip2 support not builtin the library. Unable to test/verify internal compress load/unload code\n");
+       do_close = 1;
+#endif
+#else
+       printf("WARNING: zlib support not builtin the library. Unable to test/verify internal compress load/unload code\n");
+       do_close = 1;
+#endif
+
+       if (do_close) {
+               knet_handle_free(knet_h2);
+               knet_handle_free(knet_h1);
+       }
+       flush_logs(logfds[0], stdout);
+       close_logpipes(logfds);
+       use_cur = 0;
+       free_loop();
+}
+
+int main(int argc, char *argv[])
+{
+       need_root();
+
+       test();
+
+       return PASS;
+}