[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.51.2.2 and 1.60

version 1.51.2.2, 2013/02/25 00:28:00 version 1.60, 2014/04/02 17:09:23
Line 29 
Line 29 
  * Client side routines for rump syscall proxy.   * Client side routines for rump syscall proxy.
  */   */
   
 #include "rumpuser_port.h"  #include <rump/rumpuser_port.h>
   
 /*  /*
  * We use kqueue on NetBSD, poll elsewhere.  Theoretically we could   * We use kqueue on NetBSD, poll elsewhere.  Theoretically we could
Line 38 
Line 38 
  * notifications but defer their handling to a stage where we do not   * notifications but defer their handling to a stage where we do not
  * hold the communication lock.  Taking a signal while holding on to   * hold the communication lock.  Taking a signal while holding on to
  * that lock may cause a deadlock.  Therefore, block signals throughout   * that lock may cause a deadlock.  Therefore, block signals throughout
  * the RPC when using poll.  This unfortunately means that the normal   * the RPC when using poll.  On Linux, we use signalfd in the same role
  * SIGINT way of stopping a process while it is undergoing rump kernel   * as kqueue on NetBSD to be able to take signals while waiting for a
  * RPC will not work.  If anyone know which Linux system call handles   * response from the server.
  * the above scenario correctly, I'm all ears.  
  */   */
   
 #ifdef __NetBSD__  #ifdef __NetBSD__
 #define USE_KQUEUE  #define USE_KQUEUE
 #endif  #endif
   #if defined(__linux__) && !defined(__ANDROID__)
   #define USE_SIGNALFD
   #endif
   
 __RCSID("$NetBSD$");  __RCSID("$NetBSD$");
   
Line 84  int (*host_socket)(int, int, int);
Line 86  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_fcntl)(int, int, ...);
   #ifdef __ANDROID__
   int     (*host_poll)(struct pollfd *, nfds_t, long);
   #else
 int     (*host_poll)(struct pollfd *, nfds_t, int);  int     (*host_poll)(struct pollfd *, nfds_t, int);
   #endif
 ssize_t (*host_read)(int, void *, size_t);  ssize_t (*host_read)(int, void *, size_t);
   #ifdef __ANDROID__
   int     (*host_sendmsg)(int, const struct msghdr *, unsigned int);
   #else
 ssize_t (*host_sendmsg)(int, const struct msghdr *, int);  ssize_t (*host_sendmsg)(int, const struct msghdr *, int);
   #endif
 int     (*host_setsockopt)(int, int, int, const void *, socklen_t);  int     (*host_setsockopt)(int, int, int, const void *, socklen_t);
 int     (*host_dup)(int);  int     (*host_dup)(int);
   
Line 96  int (*host_kevent)(int, const struct kev
Line 106  int (*host_kevent)(int, const struct kev
                        struct kevent *, size_t, const struct timespec *);                         struct kevent *, size_t, const struct timespec *);
 #endif  #endif
   
   #ifdef USE_SIGNALFD
   #include <sys/signalfd.h>
   
   int     (*host_signalfd)(int, const sigset_t *, int);
   #endif
   
 int     (*host_execve)(const char *, char *const[], char *const[]);  int     (*host_execve)(const char *, char *const[], char *const[]);
   
 #include "sp_common.c"  #include "sp_common.c"
   #include "rumpuser_sigtrans.c"
   
 static struct spclient clispc = {  static struct spclient clispc = {
         .spc_fd = -1,          .spc_fd = -1,
 };  };
   
 static int kq = -1;  static int holyfd;
 static sigset_t fullset;  static sigset_t fullset;
   
 static int doconnect(void);  static int doconnect(void);
Line 236  cliwaitresp(struct spclient *spc, struct
Line 253  cliwaitresp(struct spclient *spc, struct
                                  * typically we don't have a frame waiting                                   * typically we don't have a frame waiting
                                  * when we come in here, so call kevent now                                   * when we come in here, so call kevent now
                                  */                                   */
                                 rv = host_kevent(kq, NULL, 0,                                  rv = host_kevent(holyfd, NULL, 0,
                                     kev, __arraycount(kev), NULL);                                      kev, __arraycount(kev), NULL);
   
                                 if (__predict_false(rv == -1)) {                                  if (__predict_false(rv == -1)) {
Line 266  cliwaitresp(struct spclient *spc, struct
Line 283  cliwaitresp(struct spclient *spc, struct
                                  * determine what happens next.                                   * determine what happens next.
                                  */                                   */
  activity:   activity:
 #else /* USE_KQUEUE */  #else /* !USE_KQUEUE */
                                 struct pollfd pfd;                                  struct pollfd pfd[2];
   
                                 pfd.fd = clispc.spc_fd;                                  pfd[0].fd = clispc.spc_fd;
                                 pfd.events = POLLIN;                                  pfd[0].events = POLLIN;
                                   pfd[1].fd = holyfd;
                                 rv = host_poll(&pfd, 1, -1);                                  pfd[1].events = POLLIN;
   
                                   rv = host_poll(pfd, 2, -1);
                                   if (pfd[1].revents & POLLIN) {
                                           dosig = 1;
                                           goto cleanup;
                                   }
 #endif /* !USE_KQUEUE */  #endif /* !USE_KQUEUE */
   
                                 switch (readframe(spc)) {                                  switch (readframe(spc)) {
Line 590  handlereq(struct spclient *spc)
Line 613  handlereq(struct spclient *spc)
         void *mapaddr;          void *mapaddr;
         size_t maplen;          size_t maplen;
         int reqtype = spc->spc_hdr.rsp_type;          int reqtype = spc->spc_hdr.rsp_type;
           int sig;
   
         switch (reqtype) {          switch (reqtype) {
         case RUMPSP_COPYIN:          case RUMPSP_COPYIN:
Line 616  handlereq(struct spclient *spc)
Line 640  handlereq(struct spclient *spc)
                 /*LINTED*/                  /*LINTED*/
                 maplen = *(size_t *)spc->spc_buf;                  maplen = *(size_t *)spc->spc_buf;
                 mapaddr = mmap(NULL, maplen, PROT_READ|PROT_WRITE,                  mapaddr = mmap(NULL, maplen, PROT_READ|PROT_WRITE,
                     MAP_ANON, -1, 0);                      MAP_ANON|MAP_PRIVATE, -1, 0);
                 if (mapaddr == MAP_FAILED)                  if (mapaddr == MAP_FAILED)
                         mapaddr = NULL;                          mapaddr = NULL;
                 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:          case RUMPSP_RAISE:
                 DPRINTF(("rump_sp handlereq: raise sig %d\n", rhdr->rsp_signo));                  sig = rumpuser__sig_rump2host(rhdr->rsp_signo);
                 raise((int)rhdr->rsp_signo);                  DPRINTF(("rump_sp handlereq: raise sig %d\n", sig));
                   raise(sig);
                 /*                  /*
                  * We most likely have signals blocked, but the signal                   * We most likely have signals blocked, but the signal
                  * will be handled soon enough when we return.                   * will be handled soon enough when we return.
Line 674  dupgood(int myfd, int mustchange)
Line 699  dupgood(int myfd, int mustchange)
         return myfd;          return myfd;
 }  }
   
   #if defined(USE_KQUEUE)
   
   static int
   makeholyfd(void)
   {
           struct kevent kev[NSIG+1];
           int i, fd;
   
           /* setup kqueue, we want all signals and the fd */
           if ((fd = dupgood(host_kqueue(), 0)) == -1) {
                   ERRLOG(("rump_sp: cannot setup kqueue"));
                   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(fd, kev, NSIG+1, NULL, 0, NULL) == -1) {
                   ERRLOG(("rump_sp: kevent() failed"));
                   host_close(fd);
                   return -1;
           }
   
           return fd;
   }
   
   #elif defined(USE_SIGNALFD) /* !USE_KQUEUE */
   
   static int
   makeholyfd(void)
   {
   
           return host_signalfd(-1, &fullset, 0);
   }
   
   #else /* !USE_KQUEUE && !USE_SIGNALFD */
   
   static int
   makeholyfd(void)
   {
   
           return -1;
   }
   
   #endif
   
 static int  static int
 doconnect(void)  doconnect(void)
 {  {
Line 683  doconnect(void)
Line 756  doconnect(void)
         int s, error, flags;          int s, error, flags;
         ssize_t n;          ssize_t n;
   
         if (kq != -1)          if (holyfd != -1)
                 host_close(kq);                  host_close(holyfd);
         kq = -1;          holyfd = -1;
         s = -1;          s = -1;
   
         if (clispc.spc_fd != -1)          if (clispc.spc_fd != -1)
Line 756  doconnect(void)
Line 829  doconnect(void)
         clispc.spc_fd = s;          clispc.spc_fd = s;
         clispc.spc_state = SPCSTATE_RUNNING;          clispc.spc_state = SPCSTATE_RUNNING;
         clispc.spc_reconnecting = 0;          clispc.spc_reconnecting = 0;
           holyfd = makeholyfd();
 #ifdef USE_KQUEUE  
 {  
         struct kevent kev[NSIG+1];  
         int i;  
   
         /* setup kqueue, we want all signals and the fd */  
         if ((kq = dupgood(host_kqueue(), 0)) == -1) {  
                 ERRLOG(("rump_sp: cannot setup kqueue"));  
                 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) {  
                 ERRLOG(("rump_sp: kevent() failed"));  
                 return -1;  
         }  
 }  
 #endif /* USE_KQUEUE */  
   
         return 0;          return 0;
 }  }
Line 828  rumpclient_init(void)
Line 879  rumpclient_init(void)
                 return 0;                  return 0;
   
         /* kq does not traverse fork() */          /* kq does not traverse fork() */
   #ifdef USE_KQUEUE
         if (init_done != 0)          if (init_done != 0)
                 kq = -1;                  holyfd = -1;
   #endif
         init_done = mypid;          init_done = mypid;
   
         sigfillset(&fullset);          sigfillset(&fullset);
Line 880  rumpclient_init(void)
Line 933  rumpclient_init(void)
 #endif  #endif
 #endif /* USE_KQUEUE */  #endif /* USE_KQUEUE */
   
   #ifdef USE_SIGNALFD
           FINDSYM(signalfd)
   #endif
   
 #undef  FINDSYM  #undef  FINDSYM
 #undef  FINDSY2  #undef  FINDSY2
   
Line 900  rumpclient_init(void)
Line 957  rumpclient_init(void)
                 goto out;                  goto out;
   
         if ((p = getenv("RUMPCLIENT__EXECFD")) != NULL) {          if ((p = getenv("RUMPCLIENT__EXECFD")) != NULL) {
                 sscanf(p, "%d,%d", &clispc.spc_fd, &kq);                  sscanf(p, "%d,%d", &clispc.spc_fd, &holyfd);
                 unsetenv("RUMPCLIENT__EXECFD");                  unsetenv("RUMPCLIENT__EXECFD");
                 hstype = HANDSHAKE_EXEC;                  hstype = HANDSHAKE_EXEC;
         } else {          } else {
Line 929  rumpclient_init(void)
Line 986  rumpclient_init(void)
 struct rumpclient_fork {  struct rumpclient_fork {
         uint32_t fork_auth[AUTHLEN];          uint32_t fork_auth[AUTHLEN];
         struct spclient fork_spc;          struct spclient fork_spc;
         int fork_kq;          int fork_holyfd;
 };  };
   
 struct rumpclient_fork *  struct rumpclient_fork *
Line 956  rumpclient_prefork(void)
Line 1013  rumpclient_prefork(void)
         free(resp);          free(resp);
   
         rpf->fork_spc = clispc;          rpf->fork_spc = clispc;
         rpf->fork_kq = kq;          rpf->fork_holyfd = holyfd;
   
  out:   out:
         pthread_sigmask(SIG_SETMASK, &omask, NULL);          pthread_sigmask(SIG_SETMASK, &omask, NULL);
Line 973  rumpclient_fork_init(struct rumpclient_f
Line 1030  rumpclient_fork_init(struct rumpclient_f
         memset(&clispc, 0, sizeof(clispc));          memset(&clispc, 0, sizeof(clispc));
         clispc.spc_fd = osock;          clispc.spc_fd = osock;
   
         kq = -1; /* kqueue descriptor is not copied over fork() */  #ifdef USE_KQUEUE
           holyfd = -1; /* kqueue descriptor is not copied over fork() */
   #else
           if (holyfd != -1) {
                   host_close(holyfd);
                   holyfd = -1;
           }
   #endif
   
         if (doinit() == -1)          if (doinit() == -1)
                 return -1;                  return -1;
Line 1005  rumpclient_fork_vparent(struct rumpclien
Line 1069  rumpclient_fork_vparent(struct rumpclien
 {  {
   
         clispc = rpf->fork_spc;          clispc = rpf->fork_spc;
         kq = rpf->fork_kq;          holyfd = rpf->fork_holyfd;
 }  }
   
 void  void
Line 1027  rumpclient__closenotify(int *fdp, enum r
Line 1091  rumpclient__closenotify(int *fdp, enum r
   
         switch (variant) {          switch (variant) {
         case RUMPCLIENT_CLOSE_FCLOSEM:          case RUMPCLIENT_CLOSE_FCLOSEM:
                 untilfd = MAX(clispc.spc_fd, kq);                  untilfd = MAX(clispc.spc_fd, holyfd);
                 for (; fd <= untilfd; fd++) {                  for (; fd <= untilfd; fd++) {
                         if (fd == clispc.spc_fd || fd == kq)                          if (fd == clispc.spc_fd || fd == holyfd)
                                 continue;                                  continue;
                         rv = host_close(fd);                          rv = host_close(fd);
                         if (rv == -1)                          if (rv == -1)
Line 1058  rumpclient__closenotify(int *fdp, enum r
Line 1122  rumpclient__closenotify(int *fdp, enum r
                             EVFILT_READ, EV_DELETE, 0, 0, 0);                              EVFILT_READ, EV_DELETE, 0, 0, 0);
                         EV_SET(&kev[1], newfd,                          EV_SET(&kev[1], newfd,
                             EVFILT_READ, EV_ADD|EV_ENABLE, 0, 0, 0);                              EVFILT_READ, EV_ADD|EV_ENABLE, 0, 0, 0);
                         if (host_kevent(kq, kev, 2, NULL, 0, NULL) == -1) {                          if (host_kevent(holyfd, kev, 2, NULL, 0, NULL) == -1) {
                                 int sverrno = errno;                                  int sverrno = errno;
                                 host_close(newfd);                                  host_close(newfd);
                                 errno = sverrno;                                  errno = sverrno;
                                 return -1;                                  return -1;
                         }                          }}
   #endif /* !USE_KQUEUE */
                         clispc.spc_fd = newfd;                          clispc.spc_fd = newfd;
                         }  
                 }                  }
                 if (fd == kq) {                  if (holyfd != -1 && fd == holyfd) {
                         newfd = dupgood(kq, 1);                          newfd = dupgood(holyfd, 1);
                         if (newfd == -1)                          if (newfd == -1)
                                 return -1;                                  return -1;
                         kq = newfd;                          holyfd = newfd;
 #else /* USE_KQUEUE */  
                         clispc.spc_fd = newfd;  
 #endif /* !USE_KQUEUE */  
                 }                  }
                 break;                  break;
         }          }
Line 1105  rumpclient_exec(const char *path, char *
Line 1166  rumpclient_exec(const char *path, char *
         int rv, sverrno;          int rv, sverrno;
   
         snprintf(buf, sizeof(buf), "RUMPCLIENT__EXECFD=%d,%d",          snprintf(buf, sizeof(buf), "RUMPCLIENT__EXECFD=%d,%d",
             clispc.spc_fd, kq);              clispc.spc_fd, holyfd);
         envstr = malloc(strlen(buf)+1);          envstr = malloc(strlen(buf)+1);
         if (envstr == NULL) {          if (envstr == NULL) {
                 return ENOMEM;                  return ENOMEM;

Legend:
Removed from v.1.51.2.2  
changed lines
  Added in v.1.60

CVSweb <webmaster@jp.NetBSD.org>