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
);