Beispiel #1
0
/* Make the process sleep for SECONDS seconds, or until a signal arrives
   and is not ignored.  The function returns the number of seconds less
   than SECONDS which it actually slept (zero if it slept the full time).
   If a signal handler does a `longjmp' or modifies the handling of the
   SIGALRM signal while inside `sleep' call, the handling of the SIGALRM
   signal afterwards is undefined.  There is no return value to indicate
   error, but if `sleep' returns SECONDS, it probably didn't work.  */
unsigned int
__sleep (unsigned int seconds)
{
  int save_errno = errno;

  const unsigned int max
    = (unsigned int) (((unsigned long int) (~((time_t) 0))) >> 1);
  struct timespec ts = { 0, 0 };
  do
    {
      if (sizeof (ts.tv_sec) <= sizeof (seconds))
        {
          /* Since SECONDS is unsigned assigning the value to .tv_sec can
             overflow it.  In this case we have to wait in steps.  */
          ts.tv_sec += MIN (seconds, max);
          seconds -= (unsigned int) ts.tv_sec;
        }
      else
        {
          ts.tv_sec = (time_t) seconds;
          seconds = 0;
        }

      if (__nanosleep (&ts, &ts) < 0)
        /* We were interrupted.
           Return the number of (whole) seconds we have not yet slept.  */
        return seconds + ts.tv_sec;
    }
  while (seconds > 0);

  __set_errno (save_errno);

  return 0;
}
Beispiel #2
0
int
usleep (useconds_t useconds)
{
  struct timespec ts = { .tv_sec = (long int) (useconds / 1000000),
			 .tv_nsec = (long int) (useconds % 1000000) * 1000ul };

  /* Note the usleep() is a cancellation point.  But since we call
     nanosleep() which itself is a cancellation point we do not have
     to do anything here.  */
  return __nanosleep (&ts, NULL);
}
Beispiel #3
0
unsigned int
sleep (unsigned int seconds)
{
  struct timespec ts = { tv_sec: (long int) seconds, tv_nsec: 0 };
  unsigned int result;

  if (__nanosleep (&ts, &ts) == 0)
    result = 0;
  else
    /* Round remaining time.  */
    result = (unsigned int) ts.tv_sec + (ts.tv_nsec >= 500000000L);

  return result;
}
Beispiel #4
0
/* If there are no file descriptors available, then accept will fail.
   We want to delay here so the connection request can be dequeued;
   otherwise we can bounce between polling and accepting, never giving the
   request a chance to dequeue and eating an enormous amount of cpu time
   in svc_run if we're polling on many file descriptors.  */
void
__svc_accept_failed (void)
{
  if (errno == EMFILE)
    {
      struct timespec ts = { .tv_sec = 0, .tv_nsec = 50000000 };
      __nanosleep (&ts, NULL);
    }
}


void
__rpc_thread_svc_cleanup (void)
{
  struct svc_callout *svcp;

  while ((svcp = svc_head) != NULL)
    svc_unregister (svcp->sc_prog, svcp->sc_vers);
}
Beispiel #5
0
/* We are going to use the `nanosleep' syscall of the kernel.  But the
   kernel does not implement the stupid SysV SIGCHLD vs. SIG_IGN
   behaviour for this syscall.  Therefore we have to emulate it here.  */
unsigned int
__sleep (unsigned int seconds)
{
  const unsigned int max
    = (unsigned int) (((unsigned long int) (~((time_t) 0))) >> 1);
  struct timespec ts;
  sigset_t set, oset;
  unsigned int result;

  /* This is not necessary but some buggy programs depend on this.  */
  if (__glibc_unlikely (seconds == 0))
    {
#ifdef CANCELLATION_P
      CANCELLATION_P (THREAD_SELF);
#endif
      return 0;
    }

  ts.tv_sec = 0;
  ts.tv_nsec = 0;
 again:
  if (sizeof (ts.tv_sec) <= sizeof (seconds))
    {
      /* Since SECONDS is unsigned assigning the value to .tv_sec can
	 overflow it.  In this case we have to wait in steps.  */
      ts.tv_sec += MIN (seconds, max);
      seconds -= (unsigned int) ts.tv_sec;
    }
  else
    {
      ts.tv_sec = (time_t) seconds;
      seconds = 0;
    }

  /* Linux will wake up the system call, nanosleep, when SIGCHLD
     arrives even if SIGCHLD is ignored.  We have to deal with it
     in libc.  We block SIGCHLD first.  */
  __sigemptyset (&set);
  __sigaddset (&set, SIGCHLD);
  if (__sigprocmask (SIG_BLOCK, &set, &oset))
    return -1;

  /* If SIGCHLD is already blocked, we don't have to do anything.  */
  if (!__sigismember (&oset, SIGCHLD))
    {
      int saved_errno;
      struct sigaction oact;

      __sigemptyset (&set);
      __sigaddset (&set, SIGCHLD);

      /* We get the signal handler for SIGCHLD.  */
      if (__sigaction (SIGCHLD, (struct sigaction *) NULL, &oact) < 0)
	{
	  saved_errno = errno;
	  /* Restore the original signal mask.  */
	  (void) __sigprocmask (SIG_SETMASK, &oset, (sigset_t *) NULL);
	  __set_errno (saved_errno);
	  return -1;
	}

      /* Note the sleep() is a cancellation point.  But since we call
	 nanosleep() which itself is a cancellation point we do not
	 have to do anything here.  */
      if (oact.sa_handler == SIG_IGN)
	{
	  //__libc_cleanup_push (cl, &oset);

	  /* We should leave SIGCHLD blocked.  */
	  while (1)
	    {
	      result = __nanosleep (&ts, &ts);

	      if (result != 0 || seconds == 0)
		break;

	      if (sizeof (ts.tv_sec) <= sizeof (seconds))
		{
		  ts.tv_sec = MIN (seconds, max);
		  seconds -= (unsigned int) ts.tv_nsec;
		}
	    }

	  //__libc_cleanup_pop (0);

	  saved_errno = errno;
	  /* Restore the original signal mask.  */
	  (void) __sigprocmask (SIG_SETMASK, &oset, (sigset_t *) NULL);
	  __set_errno (saved_errno);

	  goto out;
	}

      /* We should unblock SIGCHLD.  Restore the original signal mask.  */
      (void) __sigprocmask (SIG_SETMASK, &oset, (sigset_t *) NULL);
    }

  result = __nanosleep (&ts, &ts);
  if (result == 0 && seconds != 0)
    goto again;

 out:
  if (result != 0)
    /* Round remaining time.  */
    result = seconds + (unsigned int) ts.tv_sec + (ts.tv_nsec >= 500000000L);

  return result;
}
Beispiel #6
0
int syscall_nanosleep(const struct timespec *req, struct timespec *rem){
    return __nanosleep(req, rem);
}
Beispiel #7
0
static bool_t
rendezvous_request (SVCXPRT *xprt, struct rpc_msg *errmsg)
{
  int sock;
  struct unix_rendezvous *r;
  struct sockaddr_un addr;
  struct sockaddr_in in_addr;
  socklen_t len;

  r = (struct unix_rendezvous *) xprt->xp_p1;
again:
  len = sizeof (struct sockaddr_un);
  if ((sock = accept (xprt->xp_sock, (struct sockaddr *) &addr, &len)) < 0)
    {
      if (errno == EINTR)
	goto again;
      if (errno == EMFILE)
        {
          struct timespec ts = { .tv_sec = 0, .tv_nsec = 50000000 };
          __nanosleep(&ts , NULL);
        }
      return FALSE;
    }
  /*
   * make a new transporter (re-uses xprt)
   */
  memset (&in_addr, '\0', sizeof (in_addr));
  in_addr.sin_family = AF_UNIX;
  xprt = makefd_xprt (sock, r->sendsize, r->recvsize);
  memcpy (&xprt->xp_raddr, &in_addr, sizeof (in_addr));
  xprt->xp_addrlen = len;
  return FALSE;		/* there is never an rpc msg to be processed */
}

static enum xprt_stat
rendezvous_stat (SVCXPRT *xprt)
{
  return XPRT_IDLE;
}

static void
svcunix_destroy (SVCXPRT *xprt)
{
  struct unix_conn *cd = (struct unix_conn *) xprt->xp_p1;

  xprt_unregister (xprt);
  __close (xprt->xp_sock);
  if (xprt->xp_port != 0)
    {
      /* a rendezvouser socket */
      xprt->xp_port = 0;
    }
  else
    {
      /* an actual connection socket */
      XDR_DESTROY (&(cd->xdrs));
    }
  mem_free ((caddr_t) cd, sizeof (struct unix_conn));
  mem_free ((caddr_t) xprt, sizeof (SVCXPRT));
}

#ifdef SCM_CREDENTIALS
struct cmessage {
  struct cmsghdr cmsg;
  struct ucred cmcred;
  /* hack to make sure we have enough memory */
  char dummy[(CMSG_ALIGN (sizeof (struct ucred)) - sizeof (struct ucred) + sizeof (long))];
};

/* XXX This is not thread safe, but since the main functions in svc.c
   and the rpcgen generated *_svc functions for the daemon are also not
   thread safe and uses static global variables, it doesn't matter. */
static struct cmessage cm;
#endif

static int
__msgread (int sock, void *data, size_t cnt)
{
  struct iovec iov;
  struct msghdr msg;
  int len;

  iov.iov_base = data;
  iov.iov_len = cnt;

  msg.msg_iov = &iov;
  msg.msg_iovlen = 1;
  msg.msg_name = NULL;
  msg.msg_namelen = 0;
#ifdef SCM_CREDENTIALS
  msg.msg_control = (caddr_t) &cm;
  msg.msg_controllen = sizeof (struct cmessage);
#endif
  msg.msg_flags = 0;

#ifdef SO_PASSCRED
  {
    int on = 1;
    if (__setsockopt (sock, SOL_SOCKET, SO_PASSCRED, &on, sizeof (on)))
      return -1;
  }
#endif

 restart:
  len = __recvmsg (sock, &msg, 0);
  if (len >= 0)
    {
      if (msg.msg_flags & MSG_CTRUNC || len == 0)
        return 0;
      else
        return len;
    }
  if (errno == EINTR)
    goto restart;
  return -1;
}

static int
__msgwrite (int sock, void *data, size_t cnt)
{
#ifndef SCM_CREDENTIALS
  /* We cannot implement this reliably.  */
  __set_errno (ENOSYS);
  return -1;
#else
  struct iovec iov;
  struct msghdr msg;
  struct cmsghdr *cmsg = &cm.cmsg;
  struct ucred cred;
  int len;

  /* XXX I'm not sure, if gete?id() is always correct, or if we should use
     get?id(). But since keyserv needs geteuid(), we have no other chance.
     It would be much better, if the kernel could pass both to the server. */
  cred.pid = __getpid ();
  cred.uid = __geteuid ();
  cred.gid = __getegid ();

  memcpy (CMSG_DATA(cmsg), &cred, sizeof (struct ucred));
  cmsg->cmsg_level = SOL_SOCKET;
  cmsg->cmsg_type = SCM_CREDENTIALS;
  cmsg->cmsg_len = sizeof(*cmsg) + sizeof(struct ucred);

  iov.iov_base = data;
  iov.iov_len = cnt;

  msg.msg_iov = &iov;
  msg.msg_iovlen = 1;
  msg.msg_name = NULL;
  msg.msg_namelen = 0;
  msg.msg_control = cmsg;
  msg.msg_controllen = CMSG_ALIGN(cmsg->cmsg_len);
  msg.msg_flags = 0;

 restart:
  len = __sendmsg (sock, &msg, 0);
  if (len >= 0)
    return len;
  if (errno == EINTR)
    goto restart;
  return -1;

#endif
}