Mon Jan 10 19:49:43 2011 UTC ()
A bunch of improvements:

* don't hold spc mutex while sending data
* use send() for the banner to avoid SIGPIPE in case a client
  connects and immediately goes away
* fix error path locking
* use kevent() instead of pollts() in the client.  Apparently that
  is the only sensible way for a library to support both multithreading
  and signal-reentrancy in a race-free manner.
  (can I catch all signals with one kevent instead of installing
  NSIG different ones??)
* mark client comm descriptor non-blocking so that clients have
  better signal-interruptibility (we now sleep in signal-accepting
  kevent() instead of signal-masked recvfrom())


(pooka)
diff -r1.14 -r1.15 src/lib/librumpclient/rumpclient.c
diff -r1.33 -r1.34 src/lib/librumpuser/rumpuser_sp.c
diff -r1.22 -r1.23 src/lib/librumpuser/sp_common.c

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

--- src/lib/librumpclient/rumpclient.c 2011/01/09 14:10:03 1.14
+++ src/lib/librumpclient/rumpclient.c 2011/01/10 19:49:43 1.15
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: rumpclient.c,v 1.14 2011/01/09 14:10:03 pooka Exp $ */ 1/* $NetBSD: rumpclient.c,v 1.15 2011/01/10 19:49:43 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 *
@@ -23,26 +23,27 @@ @@ -23,26 +23,27 @@
23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25 * SUCH DAMAGE. 25 * SUCH DAMAGE.
26 */ 26 */
27 27
28/* 28/*
29 * Client side routines for rump syscall proxy. 29 * Client side routines for rump syscall proxy.
30 */ 30 */
31 31
32#include <sys/cdefs.h> 32#include <sys/cdefs.h>
33__RCSID("$NetBSD"); 33__RCSID("$NetBSD");
34 34
35#include <sys/param.h> 35#include <sys/param.h>
 36#include <sys/event.h>
36#include <sys/mman.h> 37#include <sys/mman.h>
37#include <sys/socket.h> 38#include <sys/socket.h>
38 39
39#include <arpa/inet.h> 40#include <arpa/inet.h>
40#include <netinet/in.h> 41#include <netinet/in.h>
41#include <netinet/tcp.h> 42#include <netinet/tcp.h>
42 43
43#include <assert.h> 44#include <assert.h>
44#include <dlfcn.h> 45#include <dlfcn.h>
45#include <errno.h> 46#include <errno.h>
46#include <fcntl.h> 47#include <fcntl.h>
47#include <link.h> 48#include <link.h>
48#include <poll.h> 49#include <poll.h>
@@ -50,116 +51,123 @@ __RCSID("$NetBSD"); @@ -50,116 +51,123 @@ __RCSID("$NetBSD");
50#include <signal.h> 51#include <signal.h>
51#include <stdarg.h> 52#include <stdarg.h>
52#include <stdio.h> 53#include <stdio.h>
53#include <stdlib.h> 54#include <stdlib.h>
54#include <string.h> 55#include <string.h>
55#include <unistd.h> 56#include <unistd.h>
56 57
57#include <rump/rumpclient.h> 58#include <rump/rumpclient.h>
58 59
59#define HOSTOPS 60#define HOSTOPS
60int (*host_socket)(int, int, int); 61int (*host_socket)(int, int, int);
61int (*host_close)(int); 62int (*host_close)(int);
62int (*host_connect)(int, const struct sockaddr *, socklen_t); 63int (*host_connect)(int, const struct sockaddr *, socklen_t);
 64int (*host_fcntl)(int, int, ...);
63int (*host_poll)(struct pollfd *, nfds_t, int); 65int (*host_poll)(struct pollfd *, nfds_t, int);
64int (*host_pollts)(struct pollfd *, nfds_t, const struct timespec *, 66int (*host_pollts)(struct pollfd *, nfds_t, const struct timespec *,
65 const sigset_t *); 67 const sigset_t *);
66ssize_t (*host_read)(int, void *, size_t); 68ssize_t (*host_read)(int, void *, size_t);
67ssize_t (*host_sendto)(int, const void *, size_t, int, 69ssize_t (*host_sendto)(int, const void *, size_t, int,
68 const struct sockaddr *, socklen_t); 70 const struct sockaddr *, socklen_t);
69int (*host_setsockopt)(int, int, int, const void *, socklen_t); 71int (*host_setsockopt)(int, int, int, const void *, socklen_t);
70 72
71#include "sp_common.c" 73#include "sp_common.c"
72 74
73static struct spclient clispc = { 75static struct spclient clispc = {
74 .spc_fd = -1, 76 .spc_fd = -1,
75}; 77};
76 78
77/* 79static int kq;
78 * This version of waitresp is optimized for single-threaded clients 
79 * and is required by signal-safe clientside rump syscalls. 
80 */ 
81 
82static void 
83releasercvlock(struct spclient *spc) 
84{ 
85 
86 pthread_mutex_lock(&spc->spc_mtx); 
87 if (spc->spc_istatus == SPCSTATUS_WANTED) 
88 kickall(spc); 
89 spc->spc_istatus = SPCSTATUS_FREE; 
90} 
91 
92static sigset_t fullset; 80static sigset_t fullset;
 81
93static int 82static int
94waitresp(struct spclient *spc, struct respwait *rw, sigset_t *mask) 83waitresp(struct spclient *spc, struct respwait *rw, sigset_t *mask)
95{ 84{
96 struct pollfd pfd; 
97 int rv = 0; 
98 85
 86 pthread_mutex_lock(&spc->spc_mtx);
99 sendunlockl(spc); 87 sendunlockl(spc);
100 88
101 rw->rw_error = 0; 89 rw->rw_error = 0;
102 while (!rw->rw_done && rw->rw_error == 0 90 while (!rw->rw_done && rw->rw_error == 0
103 && spc->spc_state != SPCSTATE_DYING){ 91 && spc->spc_state != SPCSTATE_DYING){
104 /* are we free to receive? */ 92 /* are we free to receive? */
105 if (spc->spc_istatus == SPCSTATUS_FREE) { 93 if (spc->spc_istatus == SPCSTATUS_FREE) {
 94 struct kevent kev[8];
 95 int gotresp, dosig, rv, i;
 96
106 spc->spc_istatus = SPCSTATUS_BUSY; 97 spc->spc_istatus = SPCSTATUS_BUSY;
107 pthread_mutex_unlock(&spc->spc_mtx); 98 pthread_mutex_unlock(&spc->spc_mtx);
108 99
109 pfd.fd = spc->spc_fd; 100 dosig = 0;
110 pfd.events = POLLIN; 101 for (gotresp = 0; !gotresp; ) {
111 102 switch (readframe(spc)) {
112 switch (readframe(spc)) { 103 case 0:
113 case 0: 104 rv = kevent(kq, NULL, 0,
114 releasercvlock(spc); 105 kev, __arraycount(kev), NULL);
115 pthread_mutex_unlock(&spc->spc_mtx); 106 assert(rv > 0);
116 host_pollts(&pfd, 1, NULL, mask); 107 for (i = 0; i < rv; i++) {
117 pthread_mutex_lock(&spc->spc_mtx); 108 if (kev[i].filter
118 continue; 109 == EVFILT_SIGNAL)
119 case -1: 110 dosig++;
120 releasercvlock(spc); 111 }
121 rv = errno; 112 if (dosig)
122 spc->spc_state = SPCSTATE_DYING; 113 goto cleanup;
123 continue; 114
124 default: 115 continue;
125 break; 116 case -1:
126 } 117 spc->spc_state = SPCSTATE_DYING;
 118 goto cleanup;
 119 default:
 120 break;
 121 }
127 122
128 switch (spc->spc_hdr.rsp_class) { 123 switch (spc->spc_hdr.rsp_class) {
129 case RUMPSP_RESP: 124 case RUMPSP_RESP:
130 case RUMPSP_ERROR: 125 case RUMPSP_ERROR:
131 kickwaiter(spc); 126 kickwaiter(spc);
 127 gotresp = spc->spc_hdr.rsp_reqno ==
 128 rw->rw_reqno;
132 break; 129 break;
133 case RUMPSP_REQ: 130 case RUMPSP_REQ:
134 handlereq(spc); 131 handlereq(spc);
135 break; 132 break;
136 default: 133 default:
137 /* panic */ 134 /* panic */
138 break; 135 break;
 136 }
139 } 137 }
140 138
141 releasercvlock(spc); 139 cleanup:
 140 pthread_mutex_lock(&spc->spc_mtx);
 141 if (spc->spc_istatus == SPCSTATUS_WANTED)
 142 kickall(spc);
 143 spc->spc_istatus = SPCSTATUS_FREE;
 144
 145 /* take one for the team */
 146 if (dosig) {
 147 pthread_mutex_unlock(&spc->spc_mtx);
 148 pthread_sigmask(SIG_SETMASK, mask, NULL);
 149 pthread_sigmask(SIG_SETMASK, &fullset, NULL);
 150 pthread_mutex_lock(&spc->spc_mtx);
 151 }
142 } else { 152 } else {
143 spc->spc_istatus = SPCSTATUS_WANTED; 153 spc->spc_istatus = SPCSTATUS_WANTED;
144 pthread_cond_wait(&rw->rw_cv, &spc->spc_mtx); 154 pthread_cond_wait(&rw->rw_cv, &spc->spc_mtx);
145 } 155 }
146 } 156 }
147 TAILQ_REMOVE(&spc->spc_respwait, rw, rw_entries); 157 TAILQ_REMOVE(&spc->spc_respwait, rw, rw_entries);
148 pthread_mutex_unlock(&spc->spc_mtx); 158 pthread_mutex_unlock(&spc->spc_mtx);
149 pthread_cond_destroy(&rw->rw_cv); 159 pthread_cond_destroy(&rw->rw_cv);
150 160
151 if (rv) 
152 return rv; 
153 if (spc->spc_state == SPCSTATE_DYING) 161 if (spc->spc_state == SPCSTATE_DYING)
154 return ENOTCONN; 162 return ENOTCONN;
155 return rw->rw_error; 163 return rw->rw_error;
156} 164}
157 165
158 166
159static int 167static int
160syscall_req(struct spclient *spc, int sysnum, 168syscall_req(struct spclient *spc, int sysnum,
161 const void *data, size_t dlen, void **resp) 169 const void *data, size_t dlen, void **resp)
162{ 170{
163 struct rsp_hdr rhdr; 171 struct rsp_hdr rhdr;
164 struct respwait rw; 172 struct respwait rw;
165 sigset_t omask; 173 sigset_t omask;
@@ -375,28 +383,29 @@ handlereq(struct spclient *spc) @@ -375,28 +383,29 @@ handlereq(struct spclient *spc)
375 abort(); 383 abort();
376 break; 384 break;
377 } 385 }
378 386
379 spcfreebuf(spc); 387 spcfreebuf(spc);
380} 388}
381 389
382static unsigned ptab_idx; 390static unsigned ptab_idx;
383static struct sockaddr *serv_sa; 391static struct sockaddr *serv_sa;
384 392
385static int 393static int
386doconnect(void) 394doconnect(void)
387{ 395{
 396 struct kevent kev[NSIG+1];
388 char banner[MAXBANNER]; 397 char banner[MAXBANNER];
389 int s, error; 398 int s, error, flags, i;
390 ssize_t n; 399 ssize_t n;
391 400
392 s = host_socket(parsetab[ptab_idx].domain, SOCK_STREAM, 0); 401 s = host_socket(parsetab[ptab_idx].domain, SOCK_STREAM, 0);
393 if (s == -1) 402 if (s == -1)
394 return -1; 403 return -1;
395 404
396 if (host_connect(s, serv_sa, (socklen_t)serv_sa->sa_len) == -1) { 405 if (host_connect(s, serv_sa, (socklen_t)serv_sa->sa_len) == -1) {
397 error = errno; 406 error = errno;
398 fprintf(stderr, "rump_sp: client connect failed\n"); 407 fprintf(stderr, "rump_sp: client connect failed\n");
399 errno = error; 408 errno = error;
400 return -1; 409 return -1;
401 } 410 }
402 411
@@ -411,28 +420,54 @@ doconnect(void) @@ -411,28 +420,54 @@ doconnect(void)
411 error = errno; 420 error = errno;
412 fprintf(stderr, "rump_sp: failed to read banner\n"); 421 fprintf(stderr, "rump_sp: failed to read banner\n");
413 errno = error; 422 errno = error;
414 return -1; 423 return -1;
415 } 424 }
416 425
417 if (banner[n-1] != '\n') { 426 if (banner[n-1] != '\n') {
418 fprintf(stderr, "rump_sp: invalid banner\n"); 427 fprintf(stderr, "rump_sp: invalid banner\n");
419 errno = EINVAL; 428 errno = EINVAL;
420 return -1; 429 return -1;
421 } 430 }
422 banner[n] = '\0'; 431 banner[n] = '\0';
423 432
 433 flags = host_fcntl(s, F_GETFL, 0);
 434 if (host_fcntl(s, F_SETFL, flags | O_NONBLOCK) == -1) {
 435 fprintf(stderr, "rump_sp: cannot set socket fd to nonblock\n");
 436 errno = EINVAL;
 437 return -1;
 438 }
 439
424 /* parse the banner some day */ 440 /* parse the banner some day */
425 441
 442 /* setup kqueue, we want all signals and the fd */
 443 if ((kq = kqueue()) == -1) {
 444 error = errno;
 445 fprintf(stderr, "rump_sp: cannot setup kqueue");
 446 errno = error;
 447 return -1;
 448 }
 449
 450 for (i = 0; i < NSIG; i++) {
 451 EV_SET(&kev[i], i+1, EVFILT_SIGNAL, EV_ADD|EV_ENABLE, 0, 0, 0);
 452 }
 453 EV_SET(&kev[NSIG], s, EVFILT_READ, EV_ADD|EV_ENABLE, 0, 0, 0);
 454 if (kevent(kq, kev, NSIG+1, NULL, 0, NULL) == -1) {
 455 error = errno;
 456 fprintf(stderr, "rump_sp: kevent() failed");
 457 errno = error;
 458 return -1;
 459 }
 460
426 clispc.spc_fd = s; 461 clispc.spc_fd = s;
427 TAILQ_INIT(&clispc.spc_respwait); 462 TAILQ_INIT(&clispc.spc_respwait);
428 pthread_mutex_init(&clispc.spc_mtx, NULL); 463 pthread_mutex_init(&clispc.spc_mtx, NULL);
429 pthread_cond_init(&clispc.spc_cv, NULL); 464 pthread_cond_init(&clispc.spc_cv, NULL);
430 465
431 return 0; 466 return 0;
432} 467}
433 468
434void *(*rumpclient_dlsym)(void *, const char *); 469void *(*rumpclient_dlsym)(void *, const char *);
435 470
436int 471int
437rumpclient_init() 472rumpclient_init()
438{ 473{
@@ -445,26 +480,27 @@ rumpclient_init() @@ -445,26 +480,27 @@ rumpclient_init()
445 480
446 /* 481 /*
447 * sag mir, wo die symbol sind. zogen fort, der krieg beginnt. 482 * sag mir, wo die symbol sind. zogen fort, der krieg beginnt.
448 * wann wird man je verstehen? wann wird man je verstehen? 483 * wann wird man je verstehen? wann wird man je verstehen?
449 */ 484 */
450#define FINDSYM2(_name_,_syscall_) \ 485#define FINDSYM2(_name_,_syscall_) \
451 if ((host_##_name_ = rumpclient_dlsym(RTLD_NEXT, \ 486 if ((host_##_name_ = rumpclient_dlsym(RTLD_NEXT, \
452 #_syscall_)) == NULL) \ 487 #_syscall_)) == NULL) \
453 /* host_##_name_ = _syscall_ */; 488 /* host_##_name_ = _syscall_ */;
454#define FINDSYM(_name_) FINDSYM2(_name_,_name_) 489#define FINDSYM(_name_) FINDSYM2(_name_,_name_)
455 FINDSYM2(socket,__socket30); 490 FINDSYM2(socket,__socket30);
456 FINDSYM(close); 491 FINDSYM(close);
457 FINDSYM(connect); 492 FINDSYM(connect);
 493 FINDSYM(fcntl);
458 FINDSYM(poll); 494 FINDSYM(poll);
459 FINDSYM(pollts); 495 FINDSYM(pollts);
460 FINDSYM(read); 496 FINDSYM(read);
461 FINDSYM(sendto); 497 FINDSYM(sendto);
462 FINDSYM(setsockopt); 498 FINDSYM(setsockopt);
463#undef FINDSYM 499#undef FINDSYM
464#undef FINDSY2 500#undef FINDSY2
465 501
466 if ((p = getenv("RUMP_SERVER")) == NULL) { 502 if ((p = getenv("RUMP_SERVER")) == NULL) {
467 errno = ENOENT; 503 errno = ENOENT;
468 return -1; 504 return -1;
469 } 505 }
470 506
@@ -512,26 +548,28 @@ rumpclient_prefork(void) @@ -512,26 +548,28 @@ rumpclient_prefork(void)
512 548
513 memcpy(rpf->fork_auth, resp, sizeof(rpf->fork_auth)); 549 memcpy(rpf->fork_auth, resp, sizeof(rpf->fork_auth));
514 free(resp); 550 free(resp);
515 551
516 return rpf; 552 return rpf;
517} 553}
518 554
519int 555int
520rumpclient_fork_init(struct rumpclient_fork *rpf) 556rumpclient_fork_init(struct rumpclient_fork *rpf)
521{ 557{
522 int error; 558 int error;
523 559
524 host_close(clispc.spc_fd); 560 host_close(clispc.spc_fd);
 561 host_close(kq);
 562 kq = -1;
525 memset(&clispc, 0, sizeof(clispc)); 563 memset(&clispc, 0, sizeof(clispc));
526 clispc.spc_fd = -1; 564 clispc.spc_fd = -1;
527 565
528 if (doconnect() == -1) 566 if (doconnect() == -1)
529 return -1; 567 return -1;
530 568
531 error = handshake_req(&clispc, rpf->fork_auth, 0); 569 error = handshake_req(&clispc, rpf->fork_auth, 0);
532 if (error) { 570 if (error) {
533 pthread_mutex_destroy(&clispc.spc_mtx); 571 pthread_mutex_destroy(&clispc.spc_mtx);
534 pthread_cond_destroy(&clispc.spc_cv); 572 pthread_cond_destroy(&clispc.spc_cv);
535 errno = error; 573 errno = error;
536 return -1; 574 return -1;
537 } 575 }

cvs diff -r1.33 -r1.34 src/lib/librumpuser/rumpuser_sp.c (expand / switch to unified diff)

--- src/lib/librumpuser/rumpuser_sp.c 2011/01/10 11:57:53 1.33
+++ src/lib/librumpuser/rumpuser_sp.c 2011/01/10 19:49:43 1.34
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: rumpuser_sp.c,v 1.33 2011/01/10 11:57:53 pooka Exp $ */ 1/* $NetBSD: rumpuser_sp.c,v 1.34 2011/01/10 19:49:43 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 *
@@ -25,27 +25,27 @@ @@ -25,27 +25,27 @@
25 * SUCH DAMAGE. 25 * SUCH DAMAGE.
26 */ 26 */
27 27
28/* 28/*
29 * Sysproxy routines. This provides system RPC support over host sockets. 29 * Sysproxy routines. This provides system RPC support over host sockets.
30 * The most notable limitation is that the client and server must share 30 * The most notable limitation is that the client and server must share
31 * the same ABI. This does not mean that they have to be the same 31 * the same ABI. This does not mean that they have to be the same
32 * machine or that they need to run the same version of the host OS, 32 * machine or that they need to run the same version of the host OS,
33 * just that they must agree on the data structures. This even *might* 33 * just that they must agree on the data structures. This even *might*
34 * work correctly from one hardware architecture to another. 34 * work correctly from one hardware architecture to another.
35 */ 35 */
36 36
37#include <sys/cdefs.h> 37#include <sys/cdefs.h>
38__RCSID("$NetBSD: rumpuser_sp.c,v 1.33 2011/01/10 11:57:53 pooka Exp $"); 38__RCSID("$NetBSD: rumpuser_sp.c,v 1.34 2011/01/10 19:49:43 pooka Exp $");
39 39
40#include <sys/types.h> 40#include <sys/types.h>
41#include <sys/atomic.h> 41#include <sys/atomic.h>
42#include <sys/mman.h> 42#include <sys/mman.h>
43#include <sys/socket.h> 43#include <sys/socket.h>
44 44
45#include <arpa/inet.h> 45#include <arpa/inet.h>
46#include <netinet/in.h> 46#include <netinet/in.h>
47#include <netinet/tcp.h> 47#include <netinet/tcp.h>
48 48
49#include <assert.h> 49#include <assert.h>
50#include <errno.h> 50#include <errno.h>
51#include <fcntl.h> 51#include <fcntl.h>
@@ -94,40 +94,43 @@ struct prefork { @@ -94,40 +94,43 @@ struct prefork {
94 LIST_ENTRY(prefork) pf_entries; /* global list */ 94 LIST_ENTRY(prefork) pf_entries; /* global list */
95 LIST_ENTRY(prefork) pf_spcentries; /* linked from forking spc */ 95 LIST_ENTRY(prefork) pf_spcentries; /* linked from forking spc */
96}; 96};
97static LIST_HEAD(, prefork) preforks = LIST_HEAD_INITIALIZER(preforks); 97static LIST_HEAD(, prefork) preforks = LIST_HEAD_INITIALIZER(preforks);
98static pthread_mutex_t pfmtx; 98static pthread_mutex_t pfmtx;
99 99
100/* 100/*
101 * This version is for the server. It's optimized for multiple threads 101 * This version is for the server. It's optimized for multiple threads
102 * and is *NOT* reentrant wrt to signals. 102 * and is *NOT* reentrant wrt to signals.
103 */ 103 */
104static int 104static int
105waitresp(struct spclient *spc, struct respwait *rw) 105waitresp(struct spclient *spc, struct respwait *rw)
106{ 106{
 107 int spcstate;
107 int rv = 0; 108 int rv = 0;
108 109
 110 pthread_mutex_lock(&spc->spc_mtx);
109 sendunlockl(spc); 111 sendunlockl(spc);
110 while (!rw->rw_done && spc->spc_state != SPCSTATE_DYING) { 112 while (!rw->rw_done && spc->spc_state != SPCSTATE_DYING) {
111 pthread_cond_wait(&rw->rw_cv, &spc->spc_mtx); 113 pthread_cond_wait(&rw->rw_cv, &spc->spc_mtx);
112 } 114 }
113 TAILQ_REMOVE(&spc->spc_respwait, rw, rw_entries); 115 TAILQ_REMOVE(&spc->spc_respwait, rw, rw_entries);
 116 spcstate = spc->spc_state;
114 pthread_mutex_unlock(&spc->spc_mtx); 117 pthread_mutex_unlock(&spc->spc_mtx);
115 118
116 pthread_cond_destroy(&rw->rw_cv); 119 pthread_cond_destroy(&rw->rw_cv);
117 120
118 if (rv) 121 if (rv)
119 return rv; 122 return rv;
120 if (spc->spc_state == SPCSTATE_DYING) 123 if (spcstate == SPCSTATE_DYING)
121 return ENOTCONN; 124 return ENOTCONN;
122 return rw->rw_error; 125 return rw->rw_error;
123} 126}
124 127
125/* 128/*
126 * Manual wrappers, since librump does not have access to the 129 * Manual wrappers, since librump does not have access to the
127 * user namespace wrapped interfaces. 130 * user namespace wrapped interfaces.
128 */ 131 */
129 132
130static void 133static void
131lwproc_switch(struct lwp *l) 134lwproc_switch(struct lwp *l)
132{ 135{
133 136
@@ -501,27 +504,28 @@ serv_handleconn(int fd, connecthook_fn c @@ -501,27 +504,28 @@ serv_handleconn(int fd, connecthook_fn c
501 504
502 flags = fcntl(newfd, F_GETFL, 0); 505 flags = fcntl(newfd, F_GETFL, 0);
503 if (fcntl(newfd, F_SETFL, flags | O_NONBLOCK) == -1) { 506 if (fcntl(newfd, F_SETFL, flags | O_NONBLOCK) == -1) {
504 close(newfd); 507 close(newfd);
505 return 0; 508 return 0;
506 } 509 }
507 510
508 if (connhook(newfd) != 0) { 511 if (connhook(newfd) != 0) {
509 close(newfd); 512 close(newfd);
510 return 0; 513 return 0;
511 } 514 }
512 515
513 /* write out a banner for the client */ 516 /* write out a banner for the client */
514 if (write(newfd, banner, strlen(banner)) != (ssize_t)strlen(banner)) { 517 if (send(newfd, banner, strlen(banner), MSG_NOSIGNAL)
 518 != (ssize_t)strlen(banner)) {
515 close(newfd); 519 close(newfd);
516 return 0; 520 return 0;
517 } 521 }
518 522
519 /* find empty slot the simple way */ 523 /* find empty slot the simple way */
520 for (i = 0; i < MAXCLI; i++) { 524 for (i = 0; i < MAXCLI; i++) {
521 if (pfdlist[i].fd == -1 && spclist[i].spc_state == SPCSTATE_NEW) 525 if (pfdlist[i].fd == -1 && spclist[i].spc_state == SPCSTATE_NEW)
522 break; 526 break;
523 } 527 }
524 528
525 assert(i < MAXCLI); 529 assert(i < MAXCLI);
526 530
527 pfdlist[i].fd = newfd; 531 pfdlist[i].fd = newfd;

cvs diff -r1.22 -r1.23 src/lib/librumpuser/sp_common.c (expand / switch to unified diff)

--- src/lib/librumpuser/sp_common.c 2011/01/10 11:57:53 1.22
+++ src/lib/librumpuser/sp_common.c 2011/01/10 19:49:43 1.23
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: sp_common.c,v 1.22 2011/01/10 11:57:53 pooka Exp $ */ 1/* $NetBSD: sp_common.c,v 1.23 2011/01/10 19:49:43 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 *
@@ -202,48 +202,46 @@ spcresetbuf(struct spclient *spc) @@ -202,48 +202,46 @@ spcresetbuf(struct spclient *spc)
202 202
203static __inline void 203static __inline void
204spcfreebuf(struct spclient *spc) 204spcfreebuf(struct spclient *spc)
205{ 205{
206 206
207 free(spc->spc_buf); 207 free(spc->spc_buf);
208 spcresetbuf(spc); 208 spcresetbuf(spc);
209} 209}
210 210
211static void 211static void
212sendlockl(struct spclient *spc) 212sendlockl(struct spclient *spc)
213{ 213{
214 214
215 /* assert(pthread_mutex_owned) */ 
216 while (spc->spc_ostatus != SPCSTATUS_FREE) { 215 while (spc->spc_ostatus != SPCSTATUS_FREE) {
217 spc->spc_ostatus = SPCSTATUS_WANTED; 216 spc->spc_ostatus = SPCSTATUS_WANTED;
218 pthread_cond_wait(&spc->spc_cv, &spc->spc_mtx); 217 pthread_cond_wait(&spc->spc_cv, &spc->spc_mtx);
219 } 218 }
220 spc->spc_ostatus = SPCSTATUS_BUSY; 219 spc->spc_ostatus = SPCSTATUS_BUSY;
221} 220}
222 221
223static void 222static void
224sendlock(struct spclient *spc) 223sendlock(struct spclient *spc)
225{ 224{
226 225
227 pthread_mutex_lock(&spc->spc_mtx); 226 pthread_mutex_lock(&spc->spc_mtx);
228 sendlockl(spc); 227 sendlockl(spc);
229 pthread_mutex_unlock(&spc->spc_mtx); 228 pthread_mutex_unlock(&spc->spc_mtx);
230} 229}
231 230
232static void 231static void
233sendunlockl(struct spclient *spc) 232sendunlockl(struct spclient *spc)
234{ 233{
235 234
236 /* assert(pthread_mutex_owned) */ 
237 if (spc->spc_ostatus == SPCSTATUS_WANTED) 235 if (spc->spc_ostatus == SPCSTATUS_WANTED)
238 pthread_cond_broadcast(&spc->spc_cv); 236 pthread_cond_broadcast(&spc->spc_cv);
239 spc->spc_ostatus = SPCSTATUS_FREE; 237 spc->spc_ostatus = SPCSTATUS_FREE;
240} 238}
241 239
242static void 240static void
243sendunlock(struct spclient *spc) 241sendunlock(struct spclient *spc)
244{ 242{
245 243
246 pthread_mutex_lock(&spc->spc_mtx); 244 pthread_mutex_lock(&spc->spc_mtx);
247 sendunlockl(spc); 245 sendunlockl(spc);
248 pthread_mutex_unlock(&spc->spc_mtx); 246 pthread_mutex_unlock(&spc->spc_mtx);
249} 247}
@@ -288,53 +286,56 @@ dosend(struct spclient *spc, const void  @@ -288,53 +286,56 @@ dosend(struct spclient *spc, const void
288static void 286static void
289putwait(struct spclient *spc, struct respwait *rw, struct rsp_hdr *rhdr) 287putwait(struct spclient *spc, struct respwait *rw, struct rsp_hdr *rhdr)
290{ 288{
291 289
292 rw->rw_data = NULL; 290 rw->rw_data = NULL;
293 rw->rw_dlen = rw->rw_done = rw->rw_error = 0; 291 rw->rw_dlen = rw->rw_done = rw->rw_error = 0;
294 pthread_cond_init(&rw->rw_cv, NULL); 292 pthread_cond_init(&rw->rw_cv, NULL);
295 293
296 pthread_mutex_lock(&spc->spc_mtx); 294 pthread_mutex_lock(&spc->spc_mtx);
297 rw->rw_reqno = rhdr->rsp_reqno = spc->spc_nextreq++; 295 rw->rw_reqno = rhdr->rsp_reqno = spc->spc_nextreq++;
298 TAILQ_INSERT_TAIL(&spc->spc_respwait, rw, rw_entries); 296 TAILQ_INSERT_TAIL(&spc->spc_respwait, rw, rw_entries);
299 297
300 sendlockl(spc); 298 sendlockl(spc);
 299 pthread_mutex_unlock(&spc->spc_mtx);
301} 300}
302 301
303static void 302static void
304unputwait(struct spclient *spc, struct respwait *rw) 303unputwait(struct spclient *spc, struct respwait *rw)
305{ 304{
306 305
 306 pthread_mutex_lock(&spc->spc_mtx);
307 sendunlockl(spc); 307 sendunlockl(spc);
308 308
309 TAILQ_REMOVE(&spc->spc_respwait, rw, rw_entries); 309 TAILQ_REMOVE(&spc->spc_respwait, rw, rw_entries);
310 pthread_mutex_unlock(&spc->spc_mtx); 310 pthread_mutex_unlock(&spc->spc_mtx);
311 pthread_cond_destroy(&rw->rw_cv); 311 pthread_cond_destroy(&rw->rw_cv);
312} 312}
313 313
314static void 314static void
315kickwaiter(struct spclient *spc) 315kickwaiter(struct spclient *spc)
316{ 316{
317 struct respwait *rw; 317 struct respwait *rw;
318 int error = 0; 318 int error = 0;
319 319
320 pthread_mutex_lock(&spc->spc_mtx); 320 pthread_mutex_lock(&spc->spc_mtx);
321 TAILQ_FOREACH(rw, &spc->spc_respwait, rw_entries) { 321 TAILQ_FOREACH(rw, &spc->spc_respwait, rw_entries) {
322 if (rw->rw_reqno == spc->spc_hdr.rsp_reqno) 322 if (rw->rw_reqno == spc->spc_hdr.rsp_reqno)
323 break; 323 break;
324 } 324 }
325 if (rw == NULL) { 325 if (rw == NULL) {
326 DPRINTF(("no waiter found, invalid reqno %" PRIu64 "?\n", 326 DPRINTF(("no waiter found, invalid reqno %" PRIu64 "?\n",
327 spc->spc_hdr.rsp_reqno)); 327 spc->spc_hdr.rsp_reqno));
 328 pthread_mutex_unlock(&spc->spc_mtx);
328 spcfreebuf(spc); 329 spcfreebuf(spc);
329 return; 330 return;
330 } 331 }
331 DPRINTF(("rump_sp: client %p woke up waiter at %p\n", spc, rw)); 332 DPRINTF(("rump_sp: client %p woke up waiter at %p\n", spc, rw));
332 rw->rw_data = spc->spc_buf; 333 rw->rw_data = spc->spc_buf;
333 rw->rw_done = 1; 334 rw->rw_done = 1;
334 rw->rw_dlen = (size_t)(spc->spc_off - HDRSZ); 335 rw->rw_dlen = (size_t)(spc->spc_off - HDRSZ);
335 if (spc->spc_hdr.rsp_class == RUMPSP_ERROR) { 336 if (spc->spc_hdr.rsp_class == RUMPSP_ERROR) {
336 error = rw->rw_error = spc->spc_hdr.rsp_error; 337 error = rw->rw_error = spc->spc_hdr.rsp_error;
337 } 338 }
338 pthread_cond_signal(&rw->rw_cv); 339 pthread_cond_signal(&rw->rw_cv);
339 pthread_mutex_unlock(&spc->spc_mtx); 340 pthread_mutex_unlock(&spc->spc_mtx);
340 341