Mon Feb 7 15:25:41 2011 UTC ()
malloc/free aren't async-signal-safe, so avoid calling them when
signals aren't blocked.

this bug made tests/rump/rumpkern/t_sp:sigsafe rarely deadlock


(pooka)
diff -r1.25 -r1.26 src/lib/librumpclient/rumpclient.c

cvs diff -r1.25 -r1.26 src/lib/librumpclient/rumpclient.c (expand / switch to unified diff)

--- src/lib/librumpclient/rumpclient.c 2011/02/07 14:49:53 1.25
+++ src/lib/librumpclient/rumpclient.c 2011/02/07 15:25:41 1.26
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: rumpclient.c,v 1.25 2011/02/07 14:49:53 pooka Exp $ */ 1/* $NetBSD: rumpclient.c,v 1.26 2011/02/07 15:25:41 pooka Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 2010, 2011 Antti Kantee. All Rights Reserved. 4 * Copyright (c) 2010, 2011 Antti Kantee. All Rights Reserved.
5 * 5 *
6 * Redistribution and use in source and binary forms, with or without 6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions 7 * modification, are permitted provided that the following conditions
8 * are met: 8 * are met:
9 * 1. Redistributions of source code must retain the above copyright 9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer. 10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright 11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the 12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution. 13 * documentation and/or other materials provided with the distribution.
14 * 14 *
@@ -257,56 +257,53 @@ cliwaitresp(struct spclient *spc, struct @@ -257,56 +257,53 @@ cliwaitresp(struct spclient *spc, struct
257 } 257 }
258 } 258 }
259 TAILQ_REMOVE(&spc->spc_respwait, rw, rw_entries); 259 TAILQ_REMOVE(&spc->spc_respwait, rw, rw_entries);
260 pthread_mutex_unlock(&spc->spc_mtx); 260 pthread_mutex_unlock(&spc->spc_mtx);
261 pthread_cond_destroy(&rw->rw_cv); 261 pthread_cond_destroy(&rw->rw_cv);
262 262
263 if (spc->spc_generation != mygen || !imalive) { 263 if (spc->spc_generation != mygen || !imalive) {
264 return ENOTCONN; 264 return ENOTCONN;
265 } 265 }
266 return rw->rw_error; 266 return rw->rw_error;
267} 267}
268 268
269static int 269static int
270syscall_req(struct spclient *spc, int sysnum, 270syscall_req(struct spclient *spc, sigset_t *omask, int sysnum,
271 const void *data, size_t dlen, void **resp) 271 const void *data, size_t dlen, void **resp)
272{ 272{
273 struct rsp_hdr rhdr; 273 struct rsp_hdr rhdr;
274 struct respwait rw; 274 struct respwait rw;
275 sigset_t omask; 
276 int rv; 275 int rv;
277 276
278 rhdr.rsp_len = sizeof(rhdr) + dlen; 277 rhdr.rsp_len = sizeof(rhdr) + dlen;
279 rhdr.rsp_class = RUMPSP_REQ; 278 rhdr.rsp_class = RUMPSP_REQ;
280 rhdr.rsp_type = RUMPSP_SYSCALL; 279 rhdr.rsp_type = RUMPSP_SYSCALL;
281 rhdr.rsp_sysnum = sysnum; 280 rhdr.rsp_sysnum = sysnum;
282 281
283 pthread_sigmask(SIG_SETMASK, &fullset, &omask); 
284 do { 282 do {
285 putwait(spc, &rw, &rhdr); 283 putwait(spc, &rw, &rhdr);
286 if ((rv = send_with_recon(spc, &rhdr, sizeof(rhdr))) != 0) { 284 if ((rv = send_with_recon(spc, &rhdr, sizeof(rhdr))) != 0) {
287 unputwait(spc, &rw); 285 unputwait(spc, &rw);
288 continue; 286 continue;
289 } 287 }
290 if ((rv = send_with_recon(spc, data, dlen)) != 0) { 288 if ((rv = send_with_recon(spc, data, dlen)) != 0) {
291 unputwait(spc, &rw); 289 unputwait(spc, &rw);
292 continue; 290 continue;
293 } 291 }
294 292
295 rv = cliwaitresp(spc, &rw, &omask, false); 293 rv = cliwaitresp(spc, &rw, omask, false);
296 if (rv == ENOTCONN) 294 if (rv == ENOTCONN)
297 rv = EAGAIN; 295 rv = EAGAIN;
298 } while (rv == EAGAIN); 296 } while (rv == EAGAIN);
299 pthread_sigmask(SIG_SETMASK, &omask, NULL); 
300 297
301 *resp = rw.rw_data; 298 *resp = rw.rw_data;
302 return rv; 299 return rv;
303} 300}
304 301
305static int 302static int
306handshake_req(struct spclient *spc, uint32_t *auth, int cancel, bool haslock) 303handshake_req(struct spclient *spc, uint32_t *auth, int cancel, bool haslock)
307{ 304{
308 struct handshake_fork rf; 305 struct handshake_fork rf;
309 struct rsp_hdr rhdr; 306 struct rsp_hdr rhdr;
310 struct respwait rw; 307 struct respwait rw;
311 sigset_t omask; 308 sigset_t omask;
312 size_t bonus; 309 size_t bonus;
@@ -336,69 +333,66 @@ handshake_req(struct spclient *spc, uint @@ -336,69 +333,66 @@ handshake_req(struct spclient *spc, uint
336 if (auth) { 333 if (auth) {
337 memcpy(rf.rf_auth, auth, AUTHLEN*sizeof(*auth)); 334 memcpy(rf.rf_auth, auth, AUTHLEN*sizeof(*auth));
338 rf.rf_cancel = cancel; 335 rf.rf_cancel = cancel;
339 rv = send_with_recon(spc, &rf, sizeof(rf)); 336 rv = send_with_recon(spc, &rf, sizeof(rf));
340 } else { 337 } else {
341 rv = dosend(spc, getprogname(), strlen(getprogname())+1); 338 rv = dosend(spc, getprogname(), strlen(getprogname())+1);
342 } 339 }
343 if (rv || cancel) { 340 if (rv || cancel) {
344 if (haslock) 341 if (haslock)
345 unputwait_locked(spc, &rw); 342 unputwait_locked(spc, &rw);
346 else 343 else
347 unputwait(spc, &rw); 344 unputwait(spc, &rw);
348 if (cancel) { 345 if (cancel) {
349 pthread_sigmask(SIG_SETMASK, &omask, NULL); 346 goto out;
350 return rv; 
351 } 347 }
352 } else { 348 } else {
353 rv = cliwaitresp(spc, &rw, &omask, haslock); 349 rv = cliwaitresp(spc, &rw, &omask, haslock);
354 } 350 }
355 pthread_sigmask(SIG_SETMASK, &omask, NULL); 
356 if (rv) 351 if (rv)
357 return rv; 352 goto out;
358 353
359 rv = *(int *)rw.rw_data; 354 rv = *(int *)rw.rw_data;
360 free(rw.rw_data); 355 free(rw.rw_data);
361 356
 357 out:
 358 pthread_sigmask(SIG_SETMASK, &omask, NULL);
362 return rv; 359 return rv;
363} 360}
364 361
365static int 362static int
366prefork_req(struct spclient *spc, void **resp) 363prefork_req(struct spclient *spc, sigset_t *omask, void **resp)
367{ 364{
368 struct rsp_hdr rhdr; 365 struct rsp_hdr rhdr;
369 struct respwait rw; 366 struct respwait rw;
370 sigset_t omask; 
371 int rv; 367 int rv;
372 368
373 rhdr.rsp_len = sizeof(rhdr); 369 rhdr.rsp_len = sizeof(rhdr);
374 rhdr.rsp_class = RUMPSP_REQ; 370 rhdr.rsp_class = RUMPSP_REQ;
375 rhdr.rsp_type = RUMPSP_PREFORK; 371 rhdr.rsp_type = RUMPSP_PREFORK;
376 rhdr.rsp_error = 0; 372 rhdr.rsp_error = 0;
377 373
378 pthread_sigmask(SIG_SETMASK, &fullset, &omask); 
379 do { 374 do {
380 putwait(spc, &rw, &rhdr); 375 putwait(spc, &rw, &rhdr);
381 rv = send_with_recon(spc, &rhdr, sizeof(rhdr)); 376 rv = send_with_recon(spc, &rhdr, sizeof(rhdr));
382 if (rv != 0) { 377 if (rv != 0) {
383 unputwait(spc, &rw); 378 unputwait(spc, &rw);
384 continue; 379 continue;
385 } 380 }
386 381
387 rv = cliwaitresp(spc, &rw, &omask, false); 382 rv = cliwaitresp(spc, &rw, omask, false);
388 if (rv == ENOTCONN) 383 if (rv == ENOTCONN)
389 rv = EAGAIN; 384 rv = EAGAIN;
390 } while (rv == EAGAIN); 385 } while (rv == EAGAIN);
391 pthread_sigmask(SIG_SETMASK, &omask, NULL); 
392 386
393 *resp = rw.rw_data; 387 *resp = rw.rw_data;
394 return rv; 388 return rv;
395} 389}
396 390
397/* 391/*
398 * prevent response code from deadlocking with reconnect code 392 * prevent response code from deadlocking with reconnect code
399 */ 393 */
400static int 394static int
401resp_sendlock(struct spclient *spc) 395resp_sendlock(struct spclient *spc)
402{ 396{
403 int rv = 0; 397 int rv = 0;
404 398
@@ -453,44 +447,49 @@ send_anonmmap_resp(struct spclient *spc, @@ -453,44 +447,49 @@ send_anonmmap_resp(struct spclient *spc,
453 447
454 if (resp_sendlock(spc) != 0) 448 if (resp_sendlock(spc) != 0)
455 return; 449 return;
456 (void)dosend(spc, &rhdr, sizeof(rhdr)); 450 (void)dosend(spc, &rhdr, sizeof(rhdr));
457 (void)dosend(spc, &addr, sizeof(addr)); 451 (void)dosend(spc, &addr, sizeof(addr));
458 sendunlock(spc); 452 sendunlock(spc);
459} 453}
460 454
461int 455int
462rumpclient_syscall(int sysnum, const void *data, size_t dlen, 456rumpclient_syscall(int sysnum, const void *data, size_t dlen,
463 register_t *retval) 457 register_t *retval)
464{ 458{
465 struct rsp_sysresp *resp; 459 struct rsp_sysresp *resp;
 460 sigset_t omask;
466 void *rdata; 461 void *rdata;
467 int rv; 462 int rv;
468 463
 464 pthread_sigmask(SIG_SETMASK, &fullset, &omask);
 465
469 DPRINTF(("rumpsp syscall_req: syscall %d with %p/%zu\n", 466 DPRINTF(("rumpsp syscall_req: syscall %d with %p/%zu\n",
470 sysnum, data, dlen)); 467 sysnum, data, dlen));
471 468
472 rv = syscall_req(&clispc, sysnum, data, dlen, &rdata); 469 rv = syscall_req(&clispc, &omask, sysnum, data, dlen, &rdata);
473 if (rv) 470 if (rv)
474 return rv; 471 goto out;
475 472
476 resp = rdata; 473 resp = rdata;
477 DPRINTF(("rumpsp syscall_resp: syscall %d error %d, rv: %d/%d\n", 474 DPRINTF(("rumpsp syscall_resp: syscall %d error %d, rv: %d/%d\n",
478 sysnum, rv, resp->rsys_retval[0], resp->rsys_retval[1])); 475 sysnum, rv, resp->rsys_retval[0], resp->rsys_retval[1]));
479 476
480 memcpy(retval, &resp->rsys_retval, sizeof(resp->rsys_retval)); 477 memcpy(retval, &resp->rsys_retval, sizeof(resp->rsys_retval));
481 rv = resp->rsys_error; 478 rv = resp->rsys_error;
482 free(rdata); 479 free(rdata);
483 480
 481 out:
 482 pthread_sigmask(SIG_SETMASK, &omask, NULL);
484 return rv; 483 return rv;
485} 484}
486 485
487static void 486static void
488handlereq(struct spclient *spc) 487handlereq(struct spclient *spc)
489{ 488{
490 struct rsp_copydata *copydata; 489 struct rsp_copydata *copydata;
491 struct rsp_hdr *rhdr = &spc->spc_hdr; 490 struct rsp_hdr *rhdr = &spc->spc_hdr;
492 void *mapaddr; 491 void *mapaddr;
493 size_t maplen; 492 size_t maplen;
494 int reqtype = spc->spc_hdr.rsp_type; 493 int reqtype = spc->spc_hdr.rsp_type;
495 494
496 switch (reqtype) { 495 switch (reqtype) {
@@ -747,42 +746,47 @@ rumpclient_init() @@ -747,42 +746,47 @@ rumpclient_init()
747 } 746 }
748 747
749 return 0; 748 return 0;
750} 749}
751 750
752struct rumpclient_fork { 751struct rumpclient_fork {
753 uint32_t fork_auth[AUTHLEN]; 752 uint32_t fork_auth[AUTHLEN];
754}; 753};
755 754
756struct rumpclient_fork * 755struct rumpclient_fork *
757rumpclient_prefork(void) 756rumpclient_prefork(void)
758{ 757{
759 struct rumpclient_fork *rpf; 758 struct rumpclient_fork *rpf;
 759 sigset_t omask;
760 void *resp; 760 void *resp;
761 int rv; 761 int rv;
762 762
 763 pthread_sigmask(SIG_SETMASK, &fullset, &omask);
763 rpf = malloc(sizeof(*rpf)); 764 rpf = malloc(sizeof(*rpf));
764 if (rpf == NULL) 765 if (rpf == NULL)
765 return NULL; 766 return NULL;
766 767
767 if ((rv = prefork_req(&clispc, &resp)) != 0) { 768 if ((rv = prefork_req(&clispc, &omask, &resp)) != 0) {
768 free(rpf); 769 free(rpf);
769 errno = rv; 770 errno = rv;
770 return NULL; 771 rpf = NULL;
 772 goto out;
771 } 773 }
772 774
773 memcpy(rpf->fork_auth, resp, sizeof(rpf->fork_auth)); 775 memcpy(rpf->fork_auth, resp, sizeof(rpf->fork_auth));
774 free(resp); 776 free(resp);
775 777
 778 out:
 779 pthread_sigmask(SIG_SETMASK, &omask, NULL);
776 return rpf; 780 return rpf;
777} 781}
778 782
779int 783int
780rumpclient_fork_init(struct rumpclient_fork *rpf) 784rumpclient_fork_init(struct rumpclient_fork *rpf)
781{ 785{
782 int error; 786 int error;
783 int osock; 787 int osock;
784 788
785 osock = clispc.spc_fd; 789 osock = clispc.spc_fd;
786 memset(&clispc, 0, sizeof(clispc)); 790 memset(&clispc, 0, sizeof(clispc));
787 clispc.spc_fd = osock; 791 clispc.spc_fd = osock;
788 792