[BACK]Return to rumpclient.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / lib / librumpclient

Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.

Diff for /src/lib/librumpclient/rumpclient.c between version 1.14 and 1.22

version 1.14, 2011/01/09 14:10:03 version 1.22, 2011/02/05 12:38:19
Line 33 
Line 33 
 __RCSID("$NetBSD");  __RCSID("$NetBSD");
   
 #include <sys/param.h>  #include <sys/param.h>
   #include <sys/event.h>
 #include <sys/mman.h>  #include <sys/mman.h>
 #include <sys/socket.h>  #include <sys/socket.h>
   
Line 49  __RCSID("$NetBSD");
Line 50  __RCSID("$NetBSD");
 #include <pthread.h>  #include <pthread.h>
 #include <signal.h>  #include <signal.h>
 #include <stdarg.h>  #include <stdarg.h>
   #include <stdbool.h>
 #include <stdio.h>  #include <stdio.h>
 #include <stdlib.h>  #include <stdlib.h>
 #include <string.h>  #include <string.h>
Line 60  __RCSID("$NetBSD");
Line 62  __RCSID("$NetBSD");
 int     (*host_socket)(int, int, int);  int     (*host_socket)(int, int, int);
 int     (*host_close)(int);  int     (*host_close)(int);
 int     (*host_connect)(int, const struct sockaddr *, socklen_t);  int     (*host_connect)(int, const struct sockaddr *, socklen_t);
   int     (*host_fcntl)(int, int, ...);
 int     (*host_poll)(struct pollfd *, nfds_t, int);  int     (*host_poll)(struct pollfd *, nfds_t, int);
 int     (*host_pollts)(struct pollfd *, nfds_t, const struct timespec *,  
                       const sigset_t *);  
 ssize_t (*host_read)(int, void *, size_t);  ssize_t (*host_read)(int, void *, size_t);
 ssize_t (*host_sendto)(int, const void *, size_t, int,  ssize_t (*host_sendto)(int, const void *, size_t, int,
                        const struct sockaddr *, socklen_t);                         const struct sockaddr *, socklen_t);
 int     (*host_setsockopt)(int, int, int, const void *, socklen_t);  int     (*host_setsockopt)(int, int, int, const void *, socklen_t);
   
   int     (*host_kqueue)(void);
   int     (*host_kevent)(int, const struct kevent *, size_t,
                          struct kevent *, size_t, const struct timespec *);
   
 #include "sp_common.c"  #include "sp_common.c"
   
 static struct spclient clispc = {  static struct spclient clispc = {
         .spc_fd = -1,          .spc_fd = -1,
 };  };
   
 /*  static int kq = -1;
  * This version of waitresp is optimized for single-threaded clients  static sigset_t fullset;
  * and is required by signal-safe clientside rump syscalls.  
  */  
   
 static void  static int doconnect(bool);
 releasercvlock(struct spclient *spc)  static int handshake_req(struct spclient *, uint32_t *, int, bool);
   
   time_t retrytimo = RUMPCLIENT_RETRYCONN_ONCE;
   
   static int
   send_with_recon(struct spclient *spc, const void *data, size_t dlen)
 {  {
           struct timeval starttime, curtime;
           time_t prevreconmsg;
           unsigned reconretries;
           int rv;
   
         pthread_mutex_lock(&spc->spc_mtx);          for (prevreconmsg = 0, reconretries = 0;;) {
         if (spc->spc_istatus == SPCSTATUS_WANTED)                  rv = dosend(spc, data, dlen);
                 kickall(spc);                  if (__predict_false(rv == ENOTCONN || rv == EBADF)) {
         spc->spc_istatus = SPCSTATUS_FREE;                          /* no persistent connections */
                           if (retrytimo == 0)
                                   break;
   
                           if (!prevreconmsg) {
                                   prevreconmsg = time(NULL);
                                   gettimeofday(&starttime, NULL);
                           }
                           if (reconretries == 1) {
                                   if (retrytimo == RUMPCLIENT_RETRYCONN_ONCE) {
                                           rv = ENOTCONN;
                                           break;
                                   }
                                   fprintf(stderr, "rump_sp: connection to "
                                       "kernel lost, trying to reconnect ...\n");
                           } else if (time(NULL) - prevreconmsg > 120) {
                                   fprintf(stderr, "rump_sp: still trying to "
                                       "reconnect ...\n");
                                   prevreconmsg = time(NULL);
                           }
   
                           /* check that we aren't over the limit */
                           if (retrytimo > 0) {
                                   struct timeval tmp;
   
                                   gettimeofday(&curtime, NULL);
                                   timersub(&curtime, &starttime, &tmp);
                                   if (tmp.tv_sec >= retrytimo) {
                                           fprintf(stderr, "rump_sp: reconnect "
                                               "failed, %lld second timeout\n",
                                               (long long)retrytimo);
                                           return ENOTCONN;
                                   }
                           }
   
                           /* adhoc backoff timer */
                           if (reconretries < 10) {
                                   usleep(100000 * reconretries);
                           } else {
                                   sleep(MIN(10, reconretries-9));
                           }
                           reconretries++;
   
                           if ((rv = doconnect(false)) != 0)
                                   continue;
                           if ((rv = handshake_req(&clispc, NULL, 0, true)) != 0)
                                   continue;
   
                           /*
                            * ok, reconnect succesful.  we need to return to
                            * the upper layer to get the entire PDU resent.
                            */
                           if (reconretries != 1)
                                   fprintf(stderr, "rump_sp: reconnected!\n");
                           rv = EAGAIN;
                           break;
                   } else {
                           _DIAGASSERT(errno != EAGAIN);
                           break;
                   }
           }
   
           return rv;
 }  }
   
 static sigset_t fullset;  
 static int  static int
 waitresp(struct spclient *spc, struct respwait *rw, sigset_t *mask)  cliwaitresp(struct spclient *spc, struct respwait *rw, sigset_t *mask,
           bool keeplock)
 {  {
         struct pollfd pfd;          uint64_t mygen;
         int rv = 0;          bool imalive = true;
   
         sendunlockl(spc);          pthread_mutex_lock(&spc->spc_mtx);
           if (!keeplock)
                   sendunlockl(spc);
           mygen = spc->spc_generation;
   
         rw->rw_error = 0;          rw->rw_error = 0;
         while (!rw->rw_done && rw->rw_error == 0          while (!rw->rw_done && rw->rw_error == 0) {
             && spc->spc_state != SPCSTATE_DYING){                  if (__predict_false(spc->spc_generation != mygen || !imalive))
                           break;
   
                 /* are we free to receive? */                  /* are we free to receive? */
                 if (spc->spc_istatus == SPCSTATUS_FREE) {                  if (spc->spc_istatus == SPCSTATUS_FREE) {
                           struct kevent kev[8];
                           int gotresp, dosig, rv, i;
   
                         spc->spc_istatus = SPCSTATUS_BUSY;                          spc->spc_istatus = SPCSTATUS_BUSY;
                         pthread_mutex_unlock(&spc->spc_mtx);                          pthread_mutex_unlock(&spc->spc_mtx);
   
                         pfd.fd = spc->spc_fd;                          dosig = 0;
                         pfd.events = POLLIN;                          for (gotresp = 0; !gotresp; ) {
                                   switch (readframe(spc)) {
                         switch (readframe(spc)) {                                  case 0:
                         case 0:                                          rv = host_kevent(kq, NULL, 0,
                                 releasercvlock(spc);                                              kev, __arraycount(kev), NULL);
                                 pthread_mutex_unlock(&spc->spc_mtx);  
                                 host_pollts(&pfd, 1, NULL, mask);                                          /*
                                 pthread_mutex_lock(&spc->spc_mtx);                                           * XXX: don't know how this can
                                 continue;                                           * happen (timeout cannot expire
                         case -1:                                           * since there isn't one), but
                                 releasercvlock(spc);                                           * it does happen
                                 rv = errno;                                           */
                                 spc->spc_state = SPCSTATE_DYING;                                          if (__predict_false(rv == 0))
                                 continue;                                                  continue;
                         default:  
                                 break;                                          for (i = 0; i < rv; i++) {
                         }                                                  if (kev[i].filter
                                                       == EVFILT_SIGNAL)
                                                           dosig++;
                                           }
                                           if (dosig)
                                                   goto cleanup;
   
                                           continue;
                                   case -1:
                                           imalive = false;
                                           goto cleanup;
                                   default:
                                           break;
                                   }
   
                         switch (spc->spc_hdr.rsp_class) {                                  switch (spc->spc_hdr.rsp_class) {
                                 case RUMPSP_RESP:                                  case RUMPSP_RESP:
                                 case RUMPSP_ERROR:                                  case RUMPSP_ERROR:
                                         kickwaiter(spc);                                          kickwaiter(spc);
                                           gotresp = spc->spc_hdr.rsp_reqno ==
                                               rw->rw_reqno;
                                         break;                                          break;
                                 case RUMPSP_REQ:                                  case RUMPSP_REQ:
                                         handlereq(spc);                                          handlereq(spc);
Line 136  waitresp(struct spclient *spc, struct re
Line 233  waitresp(struct spclient *spc, struct re
                                 default:                                  default:
                                         /* panic */                                          /* panic */
                                         break;                                          break;
                                   }
                         }                          }
   
                         releasercvlock(spc);   cleanup:
                           pthread_mutex_lock(&spc->spc_mtx);
                           if (spc->spc_istatus == SPCSTATUS_WANTED)
                                   kickall(spc);
                           spc->spc_istatus = SPCSTATUS_FREE;
   
                           /* take one for the team */
                           if (dosig) {
                                   pthread_mutex_unlock(&spc->spc_mtx);
                                   pthread_sigmask(SIG_SETMASK, mask, NULL);
                                   pthread_sigmask(SIG_SETMASK, &fullset, NULL);
                                   pthread_mutex_lock(&spc->spc_mtx);
                           }
                 } else {                  } else {
                         spc->spc_istatus = SPCSTATUS_WANTED;                          spc->spc_istatus = SPCSTATUS_WANTED;
                         pthread_cond_wait(&rw->rw_cv, &spc->spc_mtx);                          pthread_cond_wait(&rw->rw_cv, &spc->spc_mtx);
Line 148  waitresp(struct spclient *spc, struct re
Line 258  waitresp(struct spclient *spc, struct re
         pthread_mutex_unlock(&spc->spc_mtx);          pthread_mutex_unlock(&spc->spc_mtx);
         pthread_cond_destroy(&rw->rw_cv);          pthread_cond_destroy(&rw->rw_cv);
   
         if (rv)          if (spc->spc_generation != mygen || !imalive) {
                 return rv;  
         if (spc->spc_state == SPCSTATE_DYING)  
                 return ENOTCONN;                  return ENOTCONN;
           }
         return rw->rw_error;          return rw->rw_error;
 }  }
   
   
 static int  static int
 syscall_req(struct spclient *spc, int sysnum,  syscall_req(struct spclient *spc, int sysnum,
         const void *data, size_t dlen, void **resp)          const void *data, size_t dlen, void **resp)
Line 172  syscall_req(struct spclient *spc, int sy
Line 280  syscall_req(struct spclient *spc, int sy
   
         pthread_sigmask(SIG_SETMASK, &fullset, &omask);          pthread_sigmask(SIG_SETMASK, &fullset, &omask);
         do {          do {
   
                 putwait(spc, &rw, &rhdr);                  putwait(spc, &rw, &rhdr);
                 rv = dosend(spc, &rhdr, sizeof(rhdr));                  if ((rv = send_with_recon(spc, &rhdr, sizeof(rhdr))) != 0) {
                 rv = dosend(spc, data, dlen);  
                 if (rv) {  
                         unputwait(spc, &rw);                          unputwait(spc, &rw);
                         pthread_sigmask(SIG_SETMASK, &omask, NULL);                          continue;
                         return rv;                  }
                   if ((rv = send_with_recon(spc, data, dlen)) != 0) {
                           unputwait(spc, &rw);
                           continue;
                 }                  }
   
                 rv = waitresp(spc, &rw, &omask);                  rv = cliwaitresp(spc, &rw, &omask, false);
                   if (rv == ENOTCONN)
                           rv = EAGAIN;
         } while (rv == EAGAIN);          } while (rv == EAGAIN);
         pthread_sigmask(SIG_SETMASK, &omask, NULL);          pthread_sigmask(SIG_SETMASK, &omask, NULL);
   
Line 191  syscall_req(struct spclient *spc, int sy
Line 301  syscall_req(struct spclient *spc, int sy
 }  }
   
 static int  static int
 handshake_req(struct spclient *spc, uint32_t *auth, int cancel)  handshake_req(struct spclient *spc, uint32_t *auth, int cancel, bool haslock)
 {  {
         struct handshake_fork rf;          struct handshake_fork rf;
         struct rsp_hdr rhdr;          struct rsp_hdr rhdr;
         struct respwait rw;          struct respwait rw;
         sigset_t omask;          sigset_t omask;
           size_t bonus;
         int rv;          int rv;
   
           if (auth) {
                   bonus = sizeof(rf);
           } else {
                   bonus = strlen(getprogname())+1;
           }
   
         /* performs server handshake */          /* performs server handshake */
         rhdr.rsp_len = sizeof(rhdr) + (auth ? sizeof(rf) : 0);          rhdr.rsp_len = sizeof(rhdr) + bonus;
         rhdr.rsp_class = RUMPSP_REQ;          rhdr.rsp_class = RUMPSP_REQ;
         rhdr.rsp_type = RUMPSP_HANDSHAKE;          rhdr.rsp_type = RUMPSP_HANDSHAKE;
         if (auth)          if (auth)
Line 209  handshake_req(struct spclient *spc, uint
Line 326  handshake_req(struct spclient *spc, uint
                 rhdr.rsp_handshake = HANDSHAKE_GUEST;                  rhdr.rsp_handshake = HANDSHAKE_GUEST;
   
         pthread_sigmask(SIG_SETMASK, &fullset, &omask);          pthread_sigmask(SIG_SETMASK, &fullset, &omask);
         putwait(spc, &rw, &rhdr);          if (haslock)
                   putwait_locked(spc, &rw, &rhdr);
           else
                   putwait(spc, &rw, &rhdr);
         rv = dosend(spc, &rhdr, sizeof(rhdr));          rv = dosend(spc, &rhdr, sizeof(rhdr));
         if (auth) {          if (auth) {
                 memcpy(rf.rf_auth, auth, AUTHLEN*sizeof(*auth));                  memcpy(rf.rf_auth, auth, AUTHLEN*sizeof(*auth));
                 rf.rf_cancel = cancel;                  rf.rf_cancel = cancel;
                 rv = dosend(spc, &rf, sizeof(rf));                  rv = send_with_recon(spc, &rf, sizeof(rf));
         }          } else {
         if (rv != 0 || cancel) {                  rv = dosend(spc, getprogname(), strlen(getprogname())+1);
                 unputwait(spc, &rw);          }
                 pthread_sigmask(SIG_SETMASK, &omask, NULL);          if (rv || cancel) {
                 return rv;                  if (haslock)
                           unputwait_locked(spc, &rw);
                   else
                           unputwait(spc, &rw);
                   if (cancel) {
                           pthread_sigmask(SIG_SETMASK, &omask, NULL);
                           return rv;
                   }
           } else {
                   rv = cliwaitresp(spc, &rw, &omask, haslock);
         }          }
   
         rv = waitresp(spc, &rw, &omask);  
         pthread_sigmask(SIG_SETMASK, &omask, NULL);          pthread_sigmask(SIG_SETMASK, &omask, NULL);
         if (rv)          if (rv)
                 return rv;                  return rv;
Line 247  prefork_req(struct spclient *spc, void *
Line 374  prefork_req(struct spclient *spc, void *
         rhdr.rsp_error = 0;          rhdr.rsp_error = 0;
   
         pthread_sigmask(SIG_SETMASK, &fullset, &omask);          pthread_sigmask(SIG_SETMASK, &fullset, &omask);
         putwait(spc, &rw, &rhdr);          do {
         rv = dosend(spc, &rhdr, sizeof(rhdr));                  putwait(spc, &rw, &rhdr);
         if (rv != 0) {                  rv = send_with_recon(spc, &rhdr, sizeof(rhdr));
                 unputwait(spc, &rw);                  if (rv != 0) {
                 pthread_sigmask(SIG_SETMASK, &omask, NULL);                          unputwait(spc, &rw);
                 return rv;                          continue;
         }                  }
   
         rv = waitresp(spc, &rw, &omask);                  rv = cliwaitresp(spc, &rw, &omask, false);
                   if (rv == ENOTCONN)
                           rv = EAGAIN;
           } while (rv == EAGAIN);
         pthread_sigmask(SIG_SETMASK, &omask, NULL);          pthread_sigmask(SIG_SETMASK, &omask, NULL);
   
         *resp = rw.rw_data;          *resp = rw.rw_data;
         return rv;          return rv;
 }  }
   
   /*
    * prevent response code from deadlocking with reconnect code
    */
 static int  static int
   resp_sendlock(struct spclient *spc)
   {
           int rv = 0;
   
           pthread_mutex_lock(&spc->spc_mtx);
           while (spc->spc_ostatus != SPCSTATUS_FREE) {
                   if (__predict_false(spc->spc_reconnecting)) {
                           rv = EBUSY;
                           goto out;
                   }
                   spc->spc_ostatus = SPCSTATUS_WANTED;
                   pthread_cond_wait(&spc->spc_cv, &spc->spc_mtx);
           }
           spc->spc_ostatus = SPCSTATUS_BUSY;
   
    out:
           pthread_mutex_unlock(&spc->spc_mtx);
           return rv;
   }
   
   static void
 send_copyin_resp(struct spclient *spc, uint64_t reqno, void *data, size_t dlen,  send_copyin_resp(struct spclient *spc, uint64_t reqno, void *data, size_t dlen,
         int wantstr)          int wantstr)
 {  {
         struct rsp_hdr rhdr;          struct rsp_hdr rhdr;
         int rv;  
   
         if (wantstr)          if (wantstr)
                 dlen = MIN(dlen, strlen(data)+1);                  dlen = MIN(dlen, strlen(data)+1);
Line 277  send_copyin_resp(struct spclient *spc, u
Line 431  send_copyin_resp(struct spclient *spc, u
         rhdr.rsp_type = RUMPSP_COPYIN;          rhdr.rsp_type = RUMPSP_COPYIN;
         rhdr.rsp_sysnum = 0;          rhdr.rsp_sysnum = 0;
   
         sendlock(spc);          if (resp_sendlock(spc) != 0)
         rv = dosend(spc, &rhdr, sizeof(rhdr));                  return;
         rv = dosend(spc, data, dlen);          (void)dosend(spc, &rhdr, sizeof(rhdr));
           (void)dosend(spc, data, dlen);
         sendunlock(spc);          sendunlock(spc);
   
         return rv;  
 }  }
   
 static int  static void
 send_anonmmap_resp(struct spclient *spc, uint64_t reqno, void *addr)  send_anonmmap_resp(struct spclient *spc, uint64_t reqno, void *addr)
 {  {
         struct rsp_hdr rhdr;          struct rsp_hdr rhdr;
         int rv;  
   
         rhdr.rsp_len = sizeof(rhdr) + sizeof(addr);          rhdr.rsp_len = sizeof(rhdr) + sizeof(addr);
         rhdr.rsp_reqno = reqno;          rhdr.rsp_reqno = reqno;
Line 297  send_anonmmap_resp(struct spclient *spc,
Line 449  send_anonmmap_resp(struct spclient *spc,
         rhdr.rsp_type = RUMPSP_ANONMMAP;          rhdr.rsp_type = RUMPSP_ANONMMAP;
         rhdr.rsp_sysnum = 0;          rhdr.rsp_sysnum = 0;
   
         sendlock(spc);          if (resp_sendlock(spc) != 0)
         rv = dosend(spc, &rhdr, sizeof(rhdr));                  return;
         rv = dosend(spc, &addr, sizeof(addr));          (void)dosend(spc, &rhdr, sizeof(rhdr));
           (void)dosend(spc, &addr, sizeof(addr));
         sendunlock(spc);          sendunlock(spc);
   
         return rv;  
 }  }
   
 int  int
Line 335  static void
Line 486  static void
 handlereq(struct spclient *spc)  handlereq(struct spclient *spc)
 {  {
         struct rsp_copydata *copydata;          struct rsp_copydata *copydata;
           struct rsp_hdr *rhdr = &spc->spc_hdr;
         void *mapaddr;          void *mapaddr;
         size_t maplen;          size_t maplen;
         int reqtype = spc->spc_hdr.rsp_type;          int reqtype = spc->spc_hdr.rsp_type;
Line 370  handlereq(struct spclient *spc)
Line 522  handlereq(struct spclient *spc)
                 DPRINTF(("rump_sp handlereq: anonmmap: %p\n", mapaddr));                  DPRINTF(("rump_sp handlereq: anonmmap: %p\n", mapaddr));
                 send_anonmmap_resp(spc, spc->spc_hdr.rsp_reqno, mapaddr);                  send_anonmmap_resp(spc, spc->spc_hdr.rsp_reqno, mapaddr);
                 break;                  break;
           case RUMPSP_RAISE:
                   DPRINTF(("rump_sp handlereq: raise sig %d\n", rhdr->rsp_signo));
                   raise((int)rhdr->rsp_signo);
                   /*
                    * We most likely have signals blocked, but the signal
                    * will be handled soon enough when we return.
                    */
                   break;
         default:          default:
                 printf("PANIC: INVALID TYPE %d\n", reqtype);                  printf("PANIC: INVALID TYPE %d\n", reqtype);
                 abort();                  abort();
Line 383  static unsigned ptab_idx;
Line 543  static unsigned ptab_idx;
 static struct sockaddr *serv_sa;  static struct sockaddr *serv_sa;
   
 static int  static int
 doconnect(void)  doconnect(bool noisy)
 {  {
           struct respwait rw;
           struct rsp_hdr rhdr;
           struct kevent kev[NSIG+1];
         char banner[MAXBANNER];          char banner[MAXBANNER];
         int s, error;          struct pollfd pfd;
           int s, error, flags, i;
         ssize_t n;          ssize_t n;
   
           if (kq != -1)
                   host_close(kq);
           kq = -1;
           s = -1;
   
           if (clispc.spc_fd != -1)
                   host_close(clispc.spc_fd);
           clispc.spc_fd = -1;
   
           /*
            * for reconnect, gate everyone out of the receiver code
            */
           putwait_locked(&clispc, &rw, &rhdr);
   
           pthread_mutex_lock(&clispc.spc_mtx);
           clispc.spc_reconnecting = 1;
           pthread_cond_broadcast(&clispc.spc_cv);
           clispc.spc_generation++;
           while (clispc.spc_istatus != SPCSTATUS_FREE) {
                   clispc.spc_istatus = SPCSTATUS_WANTED;
                   pthread_cond_wait(&rw.rw_cv, &clispc.spc_mtx);
           }
           kickall(&clispc);
   
           /*
            * we can release it already since we hold the
            * send lock during reconnect
            * XXX: assert it
            */
           clispc.spc_istatus = SPCSTATUS_FREE;
           pthread_mutex_unlock(&clispc.spc_mtx);
           unputwait_locked(&clispc, &rw);
   
           free(clispc.spc_buf);
           clispc.spc_off = 0;
   
         s = host_socket(parsetab[ptab_idx].domain, SOCK_STREAM, 0);          s = host_socket(parsetab[ptab_idx].domain, SOCK_STREAM, 0);
         if (s == -1)          if (s == -1)
                 return -1;                  return -1;
   
         if (host_connect(s, serv_sa, (socklen_t)serv_sa->sa_len) == -1) {          pfd.fd = s;
           pfd.events = POLLIN;
           while (host_connect(s, serv_sa, (socklen_t)serv_sa->sa_len) == -1) {
                   if (errno == EINTR)
                           continue;
                 error = errno;                  error = errno;
                 fprintf(stderr, "rump_sp: client connect failed\n");                  if (noisy)
                           fprintf(stderr, "rump_sp: client connect failed: %s\n",
                               strerror(errno));
                 errno = error;                  errno = error;
                 return -1;                  return -1;
         }          }
   
         if ((error = parsetab[ptab_idx].connhook(s)) != 0) {          if ((error = parsetab[ptab_idx].connhook(s)) != 0) {
                 error = errno;                  error = errno;
                 fprintf(stderr, "rump_sp: connect hook failed\n");                  if (noisy)
                           fprintf(stderr, "rump_sp: connect hook failed\n");
                 errno = error;                  errno = error;
                 return -1;                  return -1;
         }          }
   
         if ((n = host_read(s, banner, sizeof(banner)-1)) < 0) {          if ((n = host_read(s, banner, sizeof(banner)-1)) < 0) {
                 error = errno;                  error = errno;
                 fprintf(stderr, "rump_sp: failed to read banner\n");                  if (noisy)
                           fprintf(stderr, "rump_sp: failed to read banner\n");
                 errno = error;                  errno = error;
                 return -1;                  return -1;
         }          }
   
         if (banner[n-1] != '\n') {          if (banner[n-1] != '\n') {
                 fprintf(stderr, "rump_sp: invalid banner\n");                  if (noisy)
                           fprintf(stderr, "rump_sp: invalid banner\n");
                 errno = EINVAL;                  errno = EINVAL;
                 return -1;                  return -1;
         }          }
         banner[n] = '\0';          banner[n] = '\0';
   
         /* parse the banner some day */          /* parse the banner some day */
   
           flags = host_fcntl(s, F_GETFL, 0);
           if (host_fcntl(s, F_SETFL, flags | O_NONBLOCK) == -1) {
                   if (noisy)
                           fprintf(stderr, "rump_sp: socket fd NONBLOCK: %s\n",
                               strerror(errno));
                   errno = EINVAL;
                   return -1;
           }
         clispc.spc_fd = s;          clispc.spc_fd = s;
           clispc.spc_state = SPCSTATE_RUNNING;
           clispc.spc_reconnecting = 0;
   
           /* setup kqueue, we want all signals and the fd */
           if ((kq = host_kqueue()) == -1) {
                   error = errno;
                   if (noisy)
                           fprintf(stderr, "rump_sp: cannot setup kqueue");
                   errno = error;
                   return -1;
           }
   
           for (i = 0; i < NSIG; i++) {
                   EV_SET(&kev[i], i+1, EVFILT_SIGNAL, EV_ADD|EV_ENABLE, 0, 0, 0);
           }
           EV_SET(&kev[NSIG], clispc.spc_fd,
               EVFILT_READ, EV_ADD|EV_ENABLE, 0, 0, 0);
           if (host_kevent(kq, kev, NSIG+1, NULL, 0, NULL) == -1) {
                   error = errno;
                   if (noisy)
                           fprintf(stderr, "rump_sp: kevent() failed");
                   errno = error;
                   return -1;
           }
   
           return 0;
   }
   
   static int
   doinit(void)
   {
   
         TAILQ_INIT(&clispc.spc_respwait);          TAILQ_INIT(&clispc.spc_respwait);
         pthread_mutex_init(&clispc.spc_mtx, NULL);          pthread_mutex_init(&clispc.spc_mtx, NULL);
         pthread_cond_init(&clispc.spc_cv, NULL);          pthread_cond_init(&clispc.spc_cv, NULL);
Line 455  rumpclient_init()
Line 703  rumpclient_init()
         FINDSYM2(socket,__socket30);          FINDSYM2(socket,__socket30);
         FINDSYM(close);          FINDSYM(close);
         FINDSYM(connect);          FINDSYM(connect);
           FINDSYM(fcntl);
         FINDSYM(poll);          FINDSYM(poll);
         FINDSYM(pollts);  
         FINDSYM(read);          FINDSYM(read);
         FINDSYM(sendto);          FINDSYM(sendto);
         FINDSYM(setsockopt);          FINDSYM(setsockopt);
           FINDSYM(kqueue);
   #if !__NetBSD_Prereq__(5,99,7)
           FINDSYM(kevent);
   #else
           FINDSYM2(kevent,_sys___kevent50);
   #endif
 #undef  FINDSYM  #undef  FINDSYM
 #undef  FINDSY2  #undef  FINDSY2
   
Line 473  rumpclient_init()
Line 727  rumpclient_init()
                 return -1;                  return -1;
         }          }
   
         if (doconnect() == -1)          if (doinit() == -1)
                   return -1;
           if (doconnect(true) == -1)
                 return -1;                  return -1;
   
         error = handshake_req(&clispc, NULL, 0);          error = handshake_req(&clispc, NULL, 0, false);
         if (error) {          if (error) {
                 pthread_mutex_destroy(&clispc.spc_mtx);                  pthread_mutex_destroy(&clispc.spc_mtx);
                 pthread_cond_destroy(&clispc.spc_cv);                  pthread_cond_destroy(&clispc.spc_cv);
                 host_close(clispc.spc_fd);                  if (clispc.spc_fd != -1)
                           host_close(clispc.spc_fd);
                 errno = error;                  errno = error;
                 return -1;                  return -1;
         }          }
Line 521  rumpclient_fork_init(struct rumpclient_f
Line 778  rumpclient_fork_init(struct rumpclient_f
 {  {
         int error;          int error;
   
         host_close(clispc.spc_fd);  
         memset(&clispc, 0, sizeof(clispc));          memset(&clispc, 0, sizeof(clispc));
         clispc.spc_fd = -1;          clispc.spc_fd = -1;
           kq = -1;
   
         if (doconnect() == -1)          if (doinit() == -1)
                   return -1;
           if (doconnect(false) == -1)
                 return -1;                  return -1;
   
         error = handshake_req(&clispc, rpf->fork_auth, 0);          error = handshake_req(&clispc, rpf->fork_auth, 0, false);
         if (error) {          if (error) {
                 pthread_mutex_destroy(&clispc.spc_mtx);                  pthread_mutex_destroy(&clispc.spc_mtx);
                 pthread_cond_destroy(&clispc.spc_cv);                  pthread_cond_destroy(&clispc.spc_cv);
Line 538  rumpclient_fork_init(struct rumpclient_f
Line 797  rumpclient_fork_init(struct rumpclient_f
   
         return 0;          return 0;
 }  }
   
   void
   rumpclient_setconnretry(time_t timeout)
   {
   
           if (timeout < RUMPCLIENT_RETRYCONN_ONCE)
                   return; /* gigo */
   
           retrytimo = timeout;
   }

Legend:
Removed from v.1.14  
changed lines
  Added in v.1.22

CVSweb <webmaster@jp.NetBSD.org>