2 Unix SMB/CIFS implementation.
4 Stress test for parallel NSS & libwbclient calls.
6 Copyright (C) Ralph Wuerthner 2018
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 3 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program. If not, see <http://www.gnu.org/licenses/>.
30 #include <sys/types.h>
33 #include <sys/socket.h>
48 static void *query_nss_thread(void *ptr)
50 struct thread_state *state = ptr;
52 ssize_t nread, nwritten;
55 struct passwd pwd, *result;
58 while (time(NULL) < state->timeout) {
59 rc = getpwnam_r(state->username,
64 if (rc != 0 || result == NULL) {
65 pthread_mutex_lock(&state->lock);
67 pthread_mutex_unlock(&state->lock);
69 "getpwnam_r failed with rc='%s' result=%p\n",
74 state->nss_loop_count++;
75 pthread_mutex_lock(&state->lock);
77 pthread_mutex_unlock(&state->lock);
80 pthread_mutex_unlock(&state->lock);
83 rc = socketpair(AF_UNIX, SOCK_STREAM, 0, p);
90 * Check getpwnam_r() still works after a fork,
91 * both in parent and child.
100 rc = getpwnam_r(state->username,
105 if (rc != 0 || result == NULL) {
107 "getpwnam_r failed with rc='%s' result=%p\n",
111 nwritten = write(p[0], &rc, sizeof(int));
112 assert(nwritten == sizeof(int));
115 printf("child: getpwnam_r in child succeeded\n");
117 nwritten = write(p[0], &rc, sizeof(int));
118 assert(nwritten == sizeof(int));
124 /* Check result from child */
125 nread = read(p[1], &rc, sizeof(int));
126 if (nread != sizeof(int)) {
128 "read from child failed with errno='%s' nread=%zd\n",
137 "getpwnam_r failed in the child\n");
141 printf("parent: getpwnam_r in child succeeded\n");
143 /* Verify getpwnam_r() in parent after fork */
144 rc = getpwnam_r(state->username,
149 if (rc != 0 || result == NULL) {
151 "getpwnam_r failed with rc='%s' result=%p\n",
157 printf("parent: getpwnam_r in parent succeeded\n");
161 static void *query_wbc_thread(void *ptr)
163 struct thread_state *state = ptr;
167 ssize_t nread, nwritten;
171 while (time(NULL) < state->timeout) {
172 wbc_status = wbcGetpwnam(state->username, &ppwd);
173 if (!WBC_ERROR_IS_OK(wbc_status)) {
174 pthread_mutex_lock(&state->lock);
176 pthread_mutex_unlock(&state->lock);
178 "wbcGetpwnam failed with %s\n",
179 wbcErrorString(wbc_status));
183 state->wbc_loop_count++;
184 pthread_mutex_lock(&state->lock);
186 pthread_mutex_unlock(&state->lock);
189 pthread_mutex_unlock(&state->lock);
192 rc = socketpair(AF_UNIX, SOCK_STREAM, 0, p);
199 * Check wbcGetpwnam() still works after a fork,
200 * both in parent and child.
209 wbc_status = wbcGetpwnam(state->username, &ppwd);
210 if (!WBC_ERROR_IS_OK(wbc_status)) {
212 "wbcGetpwnam failed with %s\n",
213 wbcErrorString(wbc_status));
215 nwritten = write(p[0], &rc, sizeof(int));
216 assert(nwritten == sizeof(int));
220 printf("child: wbcGetpwnam in child succeeded\n");
222 nwritten = write(p[0], &rc, sizeof(int));
223 assert(nwritten == sizeof(int));
229 /* Check result from child */
230 nread = read(p[1], &rc, sizeof(int));
231 if (nread != sizeof(int)) {
233 "read from child failed with errno='%s' nread=%zd\n",
242 "wbcGetpwnam failed in the child\n");
246 printf("parent: wbcGetpwnam in child succeeded\n");
248 /* Verify wbcGetpwnam() in parent after fork */
249 wbc_status = wbcGetpwnam(state->username, &ppwd);
250 if (!WBC_ERROR_IS_OK(wbc_status)) {
252 "wbcGetpwnam failed with %s\n",
253 wbcErrorString(wbc_status));
258 printf("parent: wbcGetpwnam in parent succeeded\n");
262 int main(int argc, char *argv[])
265 struct thread_state state;
266 pthread_t threads[2];
269 fprintf(stderr,"%s: missing domain user\n", argv[0]);
273 state.username = argv[1];
274 state.timeout = time(NULL) + RUNTIME;
275 rc = pthread_mutex_init(&state.lock, NULL);
278 "pthread_mutex_init failed: %s\n",
283 state.nss_loop_count = 0;
284 state.wbc_loop_count = 0;
286 printf("query domain user '%s'\n", state.username);
288 /* create query threads */
289 rc = pthread_create(&threads[0], NULL, query_nss_thread, &state);
292 "creating NSS thread failed: %s\n",
296 rc = pthread_create(&threads[1], NULL, query_wbc_thread, &state);
299 "creating libwbclient thread failed: %s\n",
304 /* wait for query threads to terminate */
305 for (n = 0; n < 2; n++) {
306 rc = pthread_join(threads[n], NULL);
309 "joining query thread %i failed: %s\n",
316 fprintf(state.fail ? stderr: stdout,
317 "test %s with %i NSS and %i libwbclient calls\n",
318 state.fail ? "failed" : "passed",
319 state.nss_loop_count,
320 state.wbc_loop_count);