backup: Wire up qemu full pull backup commands over QMP
[libvirt/ericb.git] / tests / shunloadtest.c
blobc5561175b914f69afcd01554f6a53159dc28c87c
1 /*
2 * Copyright (C) 2011, 2013 Red Hat, Inc.
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library. If not, see
16 * <http://www.gnu.org/licenses/>.
21 * When libvirt initializes, it creates a thread local for storing
22 * the last virErrorPtr instance. It also registers a cleanup
23 * callback for the thread local that will be invoked whenever
24 * a thread exits.
26 * If the libvirt.so library was dlopen()'d and is dlclose()'d
27 * while there is still a thread present, then when that thread
28 * later exits, the libvirt cleanup callback will be invoked.
29 * Unfortunately libvirt.so will no longer be in memory so the
30 * callback SEGVs (if you're lucky), or invokes unlreated
31 * code at the same address as the old callback (if you're
32 * unlucky).
34 * To fix the problem libvirt is linked '-z nodelete' which
35 * prevents the code being removed from memory at dlclose().
37 * This test case demonstrates this SEGV scenario. If this
38 * test does not SEGV, then the '-z nodelete' fix is working
41 #include <config.h>
43 #define NO_LIBVIRT /* This file intentionally does not link to libvirt */
44 #include "testutils.h"
46 #ifdef linux
48 # include <dlfcn.h>
49 # include <pthread.h>
50 # include <unistd.h>
51 # include <signal.h>
53 # include "internal.h"
55 pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
56 pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
57 bool running = false;
58 bool failstart = false;
59 bool quit = false;
61 static void *threadMain(void *arg)
63 int (*startup)(void) = arg;
65 if (startup() < 0) {
66 pthread_mutex_lock(&lock);
67 failstart = true;
68 pthread_cond_signal(&cond);
69 } else {
70 pthread_mutex_lock(&lock);
71 running = true;
72 pthread_cond_signal(&cond);
75 while (!quit)
76 pthread_cond_wait(&cond, &lock);
77 pthread_mutex_unlock(&lock);
79 return NULL;
82 static void sigHandler(int sig)
84 ignore_value(write(STDERR_FILENO, "FAIL\n", 5));
85 signal(sig, SIG_DFL);
86 raise(sig);
89 /* We're not using the testutils.c main() wrapper because
90 * we don't want 'shunloadtest' itself to link against
91 * libvirt.so. We need to test dlopen()'ing of libvirt.so
93 int main(int argc ATTRIBUTE_UNUSED, char **argv)
95 void (*startup)(void);
96 pthread_t t;
97 void *lib;
98 char *theprogname;
100 theprogname = argv[0];
101 if (STRPREFIX(theprogname, "./"))
102 theprogname += 2;
104 fprintf(stderr, "TEST: %s\n", theprogname);
105 fprintf(stderr, " .%*s 1 ", 39, "");
106 signal(SIGSEGV, sigHandler);
108 if (!(lib = dlopen("./.libs/libshunload.so", RTLD_LAZY))) {
109 fprintf(stderr, "Cannot load ./.libs/libshunload.so %s\n", dlerror());
110 return 1;
112 if (!(startup = dlsym(lib, "shunloadStart"))) {
113 fprintf(stderr, "Cannot find shunloadStart %s\n", dlerror());
114 dlclose(lib);
115 return 1;
119 * Create a thread which is going to initialize libvirt
120 * and raise an error
122 pthread_create(&t, NULL, threadMain, startup);
124 /* Wait for the thread to start and call libvirt */
125 pthread_mutex_lock(&lock);
126 while (!running && !failstart)
127 pthread_cond_wait(&cond, &lock);
129 /* Close the shared library (and thus make libvirt.so
130 * non-resident */
131 dlclose(lib);
133 /* Tell the thread to quit */
134 quit = true;
135 pthread_cond_signal(&cond);
136 pthread_mutex_unlock(&lock);
138 pthread_join(t, NULL);
140 /* If we got to here the thread successfully exited without
141 * causing a SEGV !
144 if (failstart)
145 fprintf(stderr, "FAIL to initialize libvirt\n");
146 else
147 fprintf(stderr, "OK\n");
149 return 0;
152 #else
154 int main(void)
156 return EXIT_AM_SKIP;
159 #endif