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
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
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
43 #define NO_LIBVIRT /* This file intentionally does not link to libvirt */
44 #include "testutils.h"
53 # include "internal.h"
55 pthread_cond_t cond
= PTHREAD_COND_INITIALIZER
;
56 pthread_mutex_t lock
= PTHREAD_MUTEX_INITIALIZER
;
58 bool failstart
= false;
61 static void *threadMain(void *arg
)
63 int (*startup
)(void) = arg
;
66 pthread_mutex_lock(&lock
);
68 pthread_cond_signal(&cond
);
70 pthread_mutex_lock(&lock
);
72 pthread_cond_signal(&cond
);
76 pthread_cond_wait(&cond
, &lock
);
77 pthread_mutex_unlock(&lock
);
82 static void sigHandler(int sig
)
84 ignore_value(write(STDERR_FILENO
, "FAIL\n", 5));
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);
100 theprogname
= argv
[0];
101 if (STRPREFIX(theprogname
, "./"))
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());
112 if (!(startup
= dlsym(lib
, "shunloadStart"))) {
113 fprintf(stderr
, "Cannot find shunloadStart %s\n", dlerror());
119 * Create a thread which is going to initialize libvirt
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
133 /* Tell the thread to quit */
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
145 fprintf(stderr
, "FAIL to initialize libvirt\n");
147 fprintf(stderr
, "OK\n");