コード例 #1
0
ファイル: lttd.c プロジェクト: Claruarius/stblinux-2.6.37
int read_subbuffer(struct fd_pair *pair)
{
	unsigned int consumed_old, len;
	int err;
	long ret;
	off_t offset;


	err = ioctl(pair->channel, RELAY_GET_SB, &consumed_old);
	printf_verbose("cookie : %u\n", consumed_old);
	if(err != 0) {
		ret = errno;
		perror("Reserving sub buffer failed (everything is normal, it is due to concurrency)");
		goto get_error;
	}
#if 0
	err = TEMP_FAILURE_RETRY(write(pair->trace,
				pair->mmap 
					+ (consumed_old & ((pair->n_subbufs * pair->subbuf_size)-1)),
				pair->subbuf_size));

	if(err < 0) {
		ret = errno;
		perror("Error in writing to file");
		goto write_error;
	}
#endif //0
	err = ioctl(pair->channel, RELAY_GET_SB_SIZE, &len);
	if(err != 0) {
		ret = errno;
		perror("Getting sub-buffer len failed.");
		goto get_error;
	}

	offset = 0;
	while (len > 0) {
		printf_verbose("splice chan to pipe offset %lu\n",
			(unsigned long)offset);
		ret = splice(pair->channel, &offset, thread_pipe[1], NULL,
			len, SPLICE_F_MOVE | SPLICE_F_MORE);
		printf_verbose("splice chan to pipe ret %ld\n", ret);
		if (ret < 0) {
			perror("Error in relay splice");
			goto write_error;
		}
		ret = splice(thread_pipe[0], NULL, pair->trace, NULL,
			ret, SPLICE_F_MOVE | SPLICE_F_MORE);
		printf_verbose("splice pipe to file %ld\n", ret);
		if (ret < 0) {
			perror("Error in file splice");
			goto write_error;
		}
		len -= ret;
	}

#if 0
	err = fsync(pair->trace);
	if(err < 0) {
		ret = errno;
		perror("Error in writing to file");
		goto write_error;
	}
#endif //0
write_error:
	ret = 0;
	err = ioctl(pair->channel, RELAY_PUT_SB, &consumed_old);
	if(err != 0) {
		ret = errno;
		if(errno == EFAULT) {
			perror("Error in unreserving sub buffer\n");
		} else if(errno == EIO) {
			/* Should never happen with newer LTTng versions */
			perror("Reader has been pushed by the writer, last sub-buffer corrupted.");
		}
		goto get_error;
	}

get_error:
	return ret;
}
コード例 #2
0
ファイル: tst-mqueue5.c プロジェクト: Drakey83/steamlink-sdk
static int
do_test (void)
{
  int result = 0;

  char tmpfname[] = "/tmp/tst-mqueue5-barrier.XXXXXX";
  int fd = mkstemp (tmpfname);
  if (fd == -1)
    {
      printf ("cannot open temporary file: %m\n");
      return 1;
    }

  /* Make sure it is always removed.  */
  unlink (tmpfname);

  /* Create one page of data.  */
  size_t ps = sysconf (_SC_PAGESIZE);
  char data[ps];
  memset (data, '\0', ps);

  /* Write the data to the file.  */
  if (write (fd, data, ps) != (ssize_t) ps)
    {
      puts ("short write");
      return 1;
    }

  void *mem = mmap (NULL, ps, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
  if (mem == MAP_FAILED)
    {
      printf ("mmap failed: %m\n");
      return 1;
    }

  pthread_barrier_t *b2;
  b2 = (pthread_barrier_t *) (((uintptr_t) mem + __alignof (pthread_barrier_t))
			      & ~(__alignof (pthread_barrier_t) - 1));

  pthread_barrier_t *b3;
  b3 = b2 + 1;

  pthread_barrierattr_t a;
  if (pthread_barrierattr_init (&a) != 0)
    {
      puts ("barrierattr_init failed");
      return 1;
    }

  if (pthread_barrierattr_setpshared (&a, PTHREAD_PROCESS_SHARED) != 0)
    {
      puts ("barrierattr_setpshared failed, could not test");
      return 0;
    }

  if (pthread_barrier_init (b2, &a, 2) != 0)
    {
      puts ("barrier_init failed");
      return 1;
    }

  if (pthread_barrier_init (b3, &a, 3) != 0)
    {
      puts ("barrier_init failed");
      return 1;
    }

  if (pthread_barrierattr_destroy (&a) != 0)
    {
      puts ("barrierattr_destroy failed");
      return 1;
    }

  char name[sizeof "/tst-mqueue5-" + sizeof (pid_t) * 3];
  snprintf (name, sizeof (name), "/tst-mqueue5-%u", getpid ());

  struct mq_attr attr = { .mq_maxmsg = 1, .mq_msgsize = 1 };
  mqd_t q = mq_open (name, O_CREAT | O_EXCL | O_RDWR, 0600, &attr);

  if (q == (mqd_t) -1)
    {
      printf ("mq_open failed with: %m\n");
      return result;
    }
  else
    add_temp_mq (name);

  struct sigevent ev;
  memset (&ev, 0xaa, sizeof (ev));
  ev.sigev_notify = SIGEV_NONE;
  if (mq_notify (q, &ev) != 0)
    {
      printf ("mq_notify (q, { SIGEV_NONE }) failed with: %m\n");
      result = 1;
    }

  if (mq_notify (q, &ev) == 0)
    {
      puts ("second mq_notify (q, { SIGEV_NONE }) unexpectedly succeeded");
      result = 1;
    }
  else if (errno != EBUSY)
    {
      printf ("second mq_notify (q, { SIGEV_NONE }) failed with: %m\n");
      result = 1;
    }

  result |= mqsend (q);

  if (mq_notify (q, &ev) != 0)
    {
      printf ("third mq_notify (q, { SIGEV_NONE }) failed with: %m\n");
      result = 1;
    }

  result |= mqrecv (q);

  if (mq_notify (q, NULL) != 0)
    {
      printf ("mq_notify (q, NULL) failed with: %m\n");
      result = 1;
    }

  if (mq_notify (q, NULL) != 0)
    {
      /* Implementation-defined behaviour, so don't fail,
	 just inform.  */
      printf ("second mq_notify (q, NULL) failed with: %m\n");
    }

  struct sigaction sa = { .sa_sigaction = rtmin_handler,
			  .sa_flags = SA_SIGINFO };
  sigemptyset (&sa.sa_mask);
  sigaction (SIGRTMIN, &sa, NULL);

  memset (&ev, 0x55, sizeof (ev));
  ev.sigev_notify = SIGEV_SIGNAL;
  ev.sigev_signo = SIGRTMIN;
  ev.sigev_value.sival_int = 26;
  if (mq_notify (q, &ev) != 0)
    {
      printf ("mq_notify (q, { SIGEV_SIGNAL }) failed with: %m\n");
      result = 1;
    }

  ev.sigev_value.sival_ptr = &ev;
  if (mq_notify (q, &ev) == 0)
    {
      puts ("second mq_notify (q, { SIGEV_SIGNAL }) unexpectedly succeeded");
      result = 1;
    }
  else if (errno != EBUSY)
    {
      printf ("second mq_notify (q, { SIGEV_SIGNAL }) failed with: %m\n");
      result = 1;
    }

  if (rtmin_cnt != 0)
    {
      puts ("SIGRTMIN signal caught too early");
      result = 1;
    }

  result |= mqsend (q);

  if (rtmin_cnt != 1)
    {
      puts ("SIGRTMIN signal did not arrive");
      result = 1;
    }
  else if (rtmin_pid != getpid ()
	   || rtmin_uid != getuid ()
	   || rtmin_code != SI_MESGQ
	   || rtmin_sigval.sival_int != 26)
    {
      printf ("unexpected siginfo_t fields: pid %u (%u), uid %u (%u), code %d (%d), si_int %d (26)\n",
	      rtmin_pid, getpid (), rtmin_uid, getuid (),
	      rtmin_code, SI_MESGQ, rtmin_sigval.sival_int);
      result = 1;
    }

  ev.sigev_value.sival_int = 75;
  if (mq_notify (q, &ev) != 0)
    {
      printf ("third mq_notify (q, { SIGEV_SIGNAL }) failed with: %m\n");
      result = 1;
    }

  result |= mqrecv (q);

  if (mq_notify (q, NULL) != 0)
    {
      printf ("mq_notify (q, NULL) failed with: %m\n");
      result = 1;
    }

  memset (&ev, 0x33, sizeof (ev));
  ev.sigev_notify = SIGEV_NONE;
  if (mq_notify (q, &ev) != 0)
    {
      printf ("fourth mq_notify (q, { SIGEV_NONE }) failed with: %m\n");
      result = 1;
    }

  pid_t pid = fork ();
  if (pid == -1)
    {
      printf ("fork () failed: %m\n");
      mq_unlink (name);
      return 1;
    }

  if (pid == 0)
    do_child (name, b2, b3, q);

  /* Child unsuccessfully attempts to mq_notify.  */

  (void) pthread_barrier_wait (b2);

  result |= mqsend (q);

  (void) pthread_barrier_wait (b2);

  /* Child successfully calls mq_notify SIGEV_SIGNAL now.  */

  result |= mqrecv (q);

  (void) pthread_barrier_wait (b2);

  memset (&ev, 0xbb, sizeof (ev));
  ev.sigev_notify = SIGEV_SIGNAL;
  ev.sigev_signo = SIGRTMIN;
  ev.sigev_value.sival_int = 15;
  if (mq_notify (q, &ev) == 0)
    {
      puts ("fourth mq_notify (q, { SIGEV_SIGNAL }) unexpectedly succeeded");
      result = 1;
    }
  else if (errno != EBUSY)
    {
      printf ("fourth mq_notify (q, { SIGEV_SIGNAL }) failed with: %m\n");
      result = 1;
    }

  result |= mqsend (q);

  if (mq_notify (q, &ev) != 0)
    {
      printf ("fifth mq_notify (q, { SIGEV_SIGNAL }) failed with: %m\n");
      result = 1;
    }

  if (rtmin_cnt != 1)
    {
      puts ("SIGRTMIN signal caught too early");
      result = 1;
    }

  result |= mqrecv (q);

  (void) pthread_barrier_wait (b2);

  /* Child verifies caught SIGRTMIN signal.  */
  /* Child calls mq_send (q) which triggers SIGRTMIN signal here.  */

  (void) pthread_barrier_wait (b2);

  /* Child mq_open's another mqd_t for the same queue (q2).  */

  if (rtmin_cnt != 2)
    {
      puts ("SIGRTMIN signal did not arrive");
      result = 1;
    }
  else if (rtmin_pid != pid
	   || rtmin_uid != getuid ()
	   || rtmin_code != SI_MESGQ
	   || rtmin_sigval.sival_int != 15)
    {
      printf ("unexpected siginfo_t fields: pid %u (%u), uid %u (%u), code %d (%d), si_int %d (15)\n",
	      rtmin_pid, pid, rtmin_uid, getuid (),
	      rtmin_code, SI_MESGQ, rtmin_sigval.sival_int);
      result = 1;
    }

  result |= mqrecv (q);

  (void) pthread_barrier_wait (b2);

  /* Child successfully calls mq_notify { SIGEV_SIGNAL } on q2.  */

  (void) pthread_barrier_wait (b2);

  memset (&ev, 0xbb, sizeof (ev));
  ev.sigev_notify = SIGEV_NONE;
  if (mq_notify (q, &ev) == 0)
    {
      puts ("fifth mq_notify (q, { SIGEV_NONE }) unexpectedly succeeded");
      result = 1;
    }
  else if (errno != EBUSY)
    {
      printf ("fifth mq_notify (q, { SIGEV_NONE }) failed with: %m\n");
      result = 1;
    }

  (void) pthread_barrier_wait (b2);

  /* Child calls mq_close on q2, which makes the queue available again for
     notification.  */

  mqd_t q3 = mq_open (name, O_RDWR);
  if (q3 == (mqd_t) -1)
    {
      printf ("mq_open q3 in parent failed with: %m\n");
      result = 1;
    }

  (void) pthread_barrier_wait (b2);

  memset (&ev, 0x12, sizeof (ev));
  ev.sigev_notify = SIGEV_NONE;
  if (mq_notify (q3, &ev) != 0)
    {
      printf ("mq_notify (q3, { SIGEV_NONE }) failed with: %m\n");
      result = 1;
    }

  (void) pthread_barrier_wait (b2);

  /* Child unsuccessfully attempts to mq_notify { SIGEV_SIGNAL } on q.  */

  (void) pthread_barrier_wait (b2);

  if (mq_close (q3) != 0)
    {
      printf ("mq_close failed: %m\n");
      result = 1;
    }

  (void) pthread_barrier_wait (b2);

  /* Child successfully calls mq_notify { SIGEV_NONE } on q.  */
  /* Child successfully calls mq_notify NULL on q.  */

  (void) pthread_barrier_wait (b2);

  /* Child creates new thread.  */
  /* Thread blocks on mqrecv (q).  */
  /* Child sleeps for 1sec so that thread has time to reach that point.  */
  /* Child successfully calls mq_notify { SIGEV_SIGNAL } on q.  */

  (void) pthread_barrier_wait (b2);

  result |= mqsend (q);

  (void) pthread_barrier_wait (b3);

  /* Child verifies SIGRTMIN has not been sent.  */

  (void) pthread_barrier_wait (b3);

  result |= mqsend (q);

  (void) pthread_barrier_wait (b3);

  /* Thread verifies SIGRTMIN has been caught.  */
  /* Thread calls mq_notify (q, { SIGEV_NONE }) to verify notification is now
     available for registration.  */
  /* Thread calls mq_notify (q, NULL).  */

  (void) pthread_barrier_wait (b3);

  /* Child calls mq_notify (q, { SIGEV_SIGNAL }).  */

  (void) pthread_barrier_wait (b3);

  /* Thread calls mq_notify (q, NULL). */

  (void) pthread_barrier_wait (b3);

  result |= mqsend (q);
  result |= mqrecv (q);

  (void) pthread_barrier_wait (b3);

  /* Child verifies SIGRTMIN has not been sent.  */
  /* Child calls mq_notify (q, { SIGEV_SIGNAL }).  */

  (void) pthread_barrier_wait (b3);

  /* Thread opens a new O_RDONLY mqd_t (q4).  */
  /* Thread calls mq_notify (q4, NULL). */
  /* Thread calls mq_close (q4).  */

  (void) pthread_barrier_wait (b3);

  result |= mqsend (q);
  result |= mqrecv (q);

  (void) pthread_barrier_wait (b3);

  /* Child verifies SIGRTMIN has not been sent.  */
  /* Child calls mq_notify (q, { SIGEV_SIGNAL }).  */

  (void) pthread_barrier_wait (b3);

  /* Thread opens a new O_WRONLY mqd_t (q5).  */
  /* Thread calls mq_notify (q5, NULL). */
  /* Thread calls mq_close (q5).  */

  (void) pthread_barrier_wait (b3);

  result |= mqsend (q);
  result |= mqrecv (q);

  (void) pthread_barrier_wait (b3);

  /* Child verifies SIGRTMIN has not been sent.  */

  int status;
  if (TEMP_FAILURE_RETRY (waitpid (pid, &status, 0)) != pid)
    {
      puts ("waitpid failed");
      kill (pid, SIGKILL);
      result = 1;
    }
  else if (!WIFEXITED (status) || WEXITSTATUS (status))
    {
      printf ("child failed with status %d\n", status);
      result = 1;
    }

  if (mq_unlink (name) != 0)
    {
      printf ("mq_unlink failed: %m\n");
      result = 1;
    }

  if (mq_close (q) != 0)
    {
      printf ("mq_close failed: %m\n");
      result = 1;
    }

  if (mq_notify (q, NULL) == 0)
    {
      puts ("mq_notify on closed mqd_t unexpectedly succeeded");
      result = 1;
    }
  else if (errno != EBADF)
    {
      printf ("mq_notify on closed mqd_t did not fail with EBADF: %m\n");
      result = 1;
    }

  memset (&ev, 0x55, sizeof (ev));
  ev.sigev_notify = SIGEV_NONE;
  if (mq_notify (q, &ev) == 0)
    {
      puts ("mq_notify on closed mqd_t unexpectedly succeeded");
      result = 1;
    }
  else if (errno != EBADF)
    {
      printf ("mq_notify on closed mqd_t did not fail with EBADF: %m\n");
      result = 1;
    }

  return result;
}
コード例 #3
0
ファイル: modify_note_text.c プロジェクト: tylerberry/newts
int
uiuc_modify_note_text (struct newt *newt)
{
  static uid_t anon;
  static short anon_is_set = FALSE;

  struct io_f io;
  struct daddr_f daddr;
  struct note_f note;
  struct stat statbuf;
  struct flock dlock, nlock;
  time_t timet;

  if (!anon_is_set)
    {
      struct passwd *pw = getpwnam (ANON);

      anon = pw->pw_uid;
      anon_is_set = TRUE;
      endpwent ();
    }

  init (&io, &newt->nr.nfr);

  if (io.descr.d_stat & NFINVALID)
    {
      closenf (&io);
      return -1;
    }

  if (newt->nr.notenum < -1 || newt->nr.notenum > io.descr.d_nnote)
    {
      closenf (&io);
      return -1;
    }

  nlock.l_type = F_RDLCK;
  nlock.l_whence = SEEK_SET;
  nlock.l_start = (off_t) (sizeof (struct descr_f) +
                           (newt->nr.notenum * sizeof (struct note_f)));
  nlock.l_len = (off_t) sizeof (struct note_f);

  if (newt->nr.respnum == 0)
    {
      TEMP_FAILURE_RETRY (fcntl (io.fidndx, F_SETLKW, &nlock));

      getnoterec (&io, newt->nr.notenum, &note);

      fstat (io.fidtxt, &statbuf);

      time (&timet);
      if (note.n_addr.textlen > HARDMAX ||
          note.n_nresp < 0 || convert_time (&note.n_lmod) > timet ||
          convert_time (&note.n_date) > timet ||
          (off_t) (note.n_addr.textlen + note.n_addr.addr) > statbuf.st_size)
        {
          closenf (&io);
          return -1;
        }

      /* We're allowed to change the director message here; saves time. */

      if (newt->director_message)
        note.n_stat |= DIRMES;
      else
        note.n_stat &= ~DIRMES;

      if (!allow (&io, DRCTOK))
        {
          if (io.descr.d_stat & ISMODERATED)
            note.n_stat |= ISUNAPPROVED;
          else
            note.n_stat &= ~ISUNAPPROVED;
        }
      else
        note.n_stat &= ~ISUNAPPROVED;

      /* Update the note's text record */

      puttextrec (&io, newt->text, &daddr, -1);
      note.n_addr.addr = daddr.addr;
      note.n_addr.textlen = daddr.textlen;

      /* We could be dealing with a newly anonymous note.  Stupid, huh? */

      if (newt->options & NOTE_ANONYMOUS)
        {
          strncpy (note.n_auth.aname, "anonymous", NAMESZ);
          note.n_auth.aid = (int) anon;
        }

      /* Set the descriptor lock; we'll be updating modification time. */

      dlock.l_type = F_RDLCK;
      dlock.l_whence = SEEK_SET;
      dlock.l_start = 0;
      dlock.l_len = (off_t) sizeof (struct descr_f);
      TEMP_FAILURE_RETRY (fcntl (io.fidndx, F_SETLKW, &dlock));

      getdescr (&io, &io.descr);

      get_uiuc_time (&io.descr.d_lastm, newt->modified);
      get_uiuc_time (&note.n_lmod, newt->modified);
      io.descr.d_delnote++;

      nlock.l_type = F_WRLCK;
      TEMP_FAILURE_RETRY (fcntl (io.fidndx, F_SETLKW, &nlock));
      dlock.l_type = F_WRLCK;
      TEMP_FAILURE_RETRY (fcntl (io.fidndx, F_SETLKW, &dlock));

      putnoterec (&io, newt->nr.notenum, &note);

      nlock.l_type = F_UNLCK;
      fcntl (io.fidndx, F_SETLK, &nlock);

      putdescr (&io, &io.descr);

      fdatasync (io.fidndx);
      dlock.l_type = F_UNLCK;
      fcntl (io.fidndx, F_SETLK, &dlock);

      closenf (&io);
      return 0;
    }
  else
    {
      struct resp_f resp, oldresp;
      struct flock rlock;
      int offset, record;

      TEMP_FAILURE_RETRY (fcntl (io.fidndx, F_SETLKW, &nlock));

      getnoterec (&io, newt->nr.notenum, &note);

      fstat (io.fidtxt, &statbuf);

      time (&timet);
      if (note.n_addr.textlen > HARDMAX ||
          note.n_nresp < 0 || convert_time (&note.n_lmod) > timet ||
          convert_time (&note.n_date) > timet ||
          (off_t) (note.n_addr.textlen + note.n_addr.addr) > statbuf.st_size)
        {
          closenf (&io);
          return -1;
        }

      if (logical_resp (&io, newt->nr.notenum, newt->nr.respnum, &oldresp,
                        &offset, &record) == -1)
        return -1;

      rlock.l_type = F_RDLCK;
      rlock.l_whence = SEEK_SET;
      rlock.l_start = (off_t) (sizeof (int) +
                               (record * sizeof (struct resp_f)));
      rlock.l_len = (off_t) sizeof (struct resp_f);
      TEMP_FAILURE_RETRY (fcntl (io.fidrdx, F_SETLKW, &rlock));

      memcpy (&resp, &oldresp, sizeof (struct resp_f));

      /* We're allowed to change the director message here; it'll save time. */

      if (newt->director_message)
        resp.r_stat[offset] |= DIRMES;
      else
        resp.r_stat[offset] &= ~DIRMES;

      if (!allow (&io, DRCTOK))
        {
          if (io.descr.d_stat & ISMODERATED)
            note.n_stat |= ISUNAPPROVED;
          else
            note.n_stat &= ~ISUNAPPROVED;
        }
      else
        note.n_stat &= ~ISUNAPPROVED;
      /* Update the response's text record */

      puttextrec (&io, newt->text, &daddr, -1);
      resp.r_addr[offset].addr = daddr.addr;
      resp.r_addr[offset].textlen = daddr.textlen;

      /* We could be dealing with a newly anonymous note.  Stupid, huh? */

      if (newt->options & NOTE_ANONYMOUS)
        {
          strncpy (resp.r_auth[offset].aname, "anonymous", NAMESZ);
          note.n_auth.aid = (int) anon;
        }

      /* Set up the descriptor lock (we update the "updated time") */

      dlock.l_type = F_RDLCK;
      dlock.l_whence = SEEK_SET;
      dlock.l_start = 0;
      dlock.l_len = (off_t) sizeof (struct descr_f);
      TEMP_FAILURE_RETRY (fcntl (io.fidndx, F_SETLKW, &dlock));

      getdescr (&io, &io.descr);

      get_uiuc_time (&io.descr.d_lastm, newt->modified);
      get_uiuc_time (&note.n_lmod, newt->modified);
      io.descr.d_delresp++;

      rlock.l_type = F_WRLCK;
      TEMP_FAILURE_RETRY (fcntl (io.fidrdx, F_SETLKW, &rlock));
      nlock.l_type = F_WRLCK;
      TEMP_FAILURE_RETRY (fcntl (io.fidndx, F_SETLKW, &nlock));
      dlock.l_type = F_WRLCK;
      TEMP_FAILURE_RETRY (fcntl (io.fidndx, F_SETLKW, &dlock));

      putresprec (&io, record, &resp);

      putnoterec (&io, newt->nr.notenum, &note);

      nlock.l_type = F_UNLCK;
      fcntl (io.fidndx, F_SETLK, &nlock);

      putdescr (&io, &io.descr);

      fdatasync (io.fidrdx);
      fdatasync (io.fidndx);
      dlock.l_type = F_UNLCK;
      fcntl (io.fidndx, F_SETLK, &dlock);
      rlock.l_type = F_UNLCK;
      fcntl (io.fidrdx, F_SETLK, &rlock);

      closenf (&io);
      return 0;
    }
}
コード例 #4
0
ファイル: task_cray.c プロジェクト: BYUHPC/slurm
/*
 * Update the number of running steps on the node
 * Set val to 1 to increment and -1 to decrement the value
 * Returns the new value, or -1 on error
 */
static int _update_num_steps(int val)
{
	int rc, fd, num_steps = 0;
	ssize_t size;
	off_t offset;
	struct flock lock;

	// Sanity check the argument
	if (val != 1 && val != -1) {
		CRAY_ERR("invalid val %d", val);
		return -1;
	}

	// Open the file
	fd = open(NUM_STEPS_FILE, O_RDWR | O_CREAT, 0644);
	if (fd == -1) {
		CRAY_ERR("open failed: %m");
		return -1;
	}

	// Exclusive lock on the first byte of the file
	// Automatically released when the file descriptor is closed
	lock.l_type = F_WRLCK;
	lock.l_whence = SEEK_SET;
	lock.l_start = 0;
	lock.l_len = sizeof(int);
	rc = fcntl(fd, F_SETLKW, &lock);
	if (rc == -1) {
		CRAY_ERR("fcntl failed: %m");
		TEMP_FAILURE_RETRY(close(fd));
		return -1;
	}

	// Read the value
	size = read(fd, &num_steps, sizeof(int));
	if (size == -1) {
		CRAY_ERR("read failed: %m");
		TEMP_FAILURE_RETRY(close(fd));
		return -1;
	} else if (size == 0) {
		// Value doesn't exist, must be the first step
		num_steps = 0;
	}

	// Increment or decrement and check result
	num_steps += val;
	if (num_steps < 0) {
		CRAY_ERR("Less than 0 steps on the node");
		TEMP_FAILURE_RETRY(close(fd));
		return 0;
	}

	// Write the new value
	offset = lseek(fd, 0, SEEK_SET);
	if (offset == -1) {
		CRAY_ERR("fseek failed: %m");
		TEMP_FAILURE_RETRY(close(fd));
		return -1;
	}
	size = write(fd, &num_steps, sizeof(int));
	if (size < sizeof(int)) {
		CRAY_ERR("write failed: %m");
		TEMP_FAILURE_RETRY(close(fd));
		return -1;
	}
	if (debug_flags & DEBUG_FLAG_TASK) {
		debug("Wrote %d steps to %s", num_steps, NUM_STEPS_FILE);
	}

	TEMP_FAILURE_RETRY(close(fd));
	return num_steps;
}
コード例 #5
0
static void handle_request(int fd) {
  ALOGV("handle_request(%d)\n", fd);

  debugger_request_t request;
  memset(&request, 0, sizeof(request));
  int status = read_request(fd, &request);
  if (!status) {
    ALOGV("BOOM: pid=%d uid=%d gid=%d tid=%d\n",
         request.pid, request.uid, request.gid, request.tid);

#if defined(__LP64__)
    // On 64 bit systems, requests to dump 32 bit and 64 bit tids come
    // to the 64 bit debuggerd. If the process is a 32 bit executable,
    // redirect the request to the 32 bit debuggerd.
    if (is32bit(request.tid)) {
      // Only dump backtrace and dump tombstone requests can be redirected.
      if (request.action == DEBUGGER_ACTION_DUMP_BACKTRACE
          || request.action == DEBUGGER_ACTION_DUMP_TOMBSTONE) {
        redirect_to_32(fd, &request);
      } else {
        ALOGE("debuggerd: Not allowed to redirect action %d to 32 bit debuggerd\n",
              request.action);
      }
      close(fd);
      return;
    }
#endif

    // At this point, the thread that made the request is blocked in
    // a read() call.  If the thread has crashed, then this gives us
    // time to PTRACE_ATTACH to it before it has a chance to really fault.
    //
    // The PTRACE_ATTACH sends a SIGSTOP to the target process, but it
    // won't necessarily have stopped by the time ptrace() returns.  (We
    // currently assume it does.)  We write to the file descriptor to
    // ensure that it can run as soon as we call PTRACE_CONT below.
    // See details in bionic/libc/linker/debugger.c, in function
    // debugger_signal_handler().
    if (ptrace(PTRACE_ATTACH, request.tid, 0, 0)) {
      ALOGE("ptrace attach failed: %s\n", strerror(errno));
    } else {
      bool detach_failed = false;
      bool tid_unresponsive = false;
      bool attach_gdb = should_attach_gdb(&request);
      if (TEMP_FAILURE_RETRY(write(fd, "\0", 1)) != 1) {
        ALOGE("failed responding to client: %s\n", strerror(errno));
      } else {
        char* tombstone_path = NULL;

        if (request.action == DEBUGGER_ACTION_CRASH) {
          close(fd);
          fd = -1;
        }

        int total_sleep_time_usec = 0;
        for (;;) {
          int signal = wait_for_sigstop(request.tid, &total_sleep_time_usec, &detach_failed);
          if (signal == -1) {
            tid_unresponsive = true;
            break;
          }

          switch (signal) {
            case SIGSTOP:
              if (request.action == DEBUGGER_ACTION_DUMP_TOMBSTONE) {
                ALOGV("stopped -- dumping to tombstone\n");
                tombstone_path = engrave_tombstone(request.pid, request.tid,
                                                   signal, request.original_si_code,
                                                   request.abort_msg_address, true,
                                                   &detach_failed, &total_sleep_time_usec);
              } else if (request.action == DEBUGGER_ACTION_DUMP_BACKTRACE) {
                ALOGV("stopped -- dumping to fd\n");
                dump_backtrace(fd, -1, request.pid, request.tid, &detach_failed,
                               &total_sleep_time_usec);
              } else {
                ALOGV("stopped -- continuing\n");
                status = ptrace(PTRACE_CONT, request.tid, 0, 0);
                if (status) {
                  ALOGE("ptrace continue failed: %s\n", strerror(errno));
                }
                continue; // loop again
              }
              break;

            case SIGABRT:
            case SIGBUS:
            case SIGFPE:
            case SIGILL:
            case SIGSEGV:
#ifdef SIGSTKFLT
            case SIGSTKFLT:
#endif
            case SIGTRAP:
              ALOGV("stopped -- fatal signal\n");
              // Send a SIGSTOP to the process to make all of
              // the non-signaled threads stop moving.  Without
              // this we get a lot of "ptrace detach failed:
              // No such process".
              kill(request.pid, SIGSTOP);
              // don't dump sibling threads when attaching to GDB because it
              // makes the process less reliable, apparently...
              tombstone_path = engrave_tombstone(request.pid, request.tid,
                                                 signal, request.original_si_code,
                                                 request.abort_msg_address, !attach_gdb,
                                                 &detach_failed, &total_sleep_time_usec);
              break;

            default:
              ALOGE("process stopped due to unexpected signal %d\n", signal);
              break;
          }
          break;
        }

        if (request.action == DEBUGGER_ACTION_DUMP_TOMBSTONE) {
          if (tombstone_path) {
            write(fd, tombstone_path, strlen(tombstone_path));
          }
          close(fd);
          fd = -1;
        }
        free(tombstone_path);
      }

      if (!tid_unresponsive) {
        ALOGV("detaching");
        if (attach_gdb) {
          // stop the process so we can debug
          kill(request.pid, SIGSTOP);
        }
        if (ptrace(PTRACE_DETACH, request.tid, 0, 0)) {
          ALOGE("ptrace detach from %d failed: %s", request.tid, strerror(errno));
          detach_failed = true;
        } else if (attach_gdb) {
          // if debug.db.uid is set, its value indicates if we should wait
          // for user action for the crashing process.
          // in this case, we log a message and turn the debug LED on
          // waiting for a gdb connection (for instance)
          wait_for_user_action(request);
        }
      }

      // resume stopped process (so it can crash in peace).
      kill(request.pid, SIGCONT);

      // If we didn't successfully detach, we're still the parent, and the
      // actual parent won't receive a death notification via wait(2).  At this point
      // there's not much we can do about that.
      if (detach_failed) {
        ALOGE("debuggerd committing suicide to free the zombie!\n");
        kill(getpid(), SIGKILL);
      }
    }

  }
  if (fd >= 0) {
    close(fd);
  }
}
コード例 #6
0
static int
do_test (void)
{
  int fd[2];
  if (pipe (fd) != 0)
    {
      puts ("pipe failed");
      exit (1);
    }

  /* Not interested in knowing when the pipe is closed.  */
  if (sigignore (SIGPIPE) != 0)
    {
      puts ("sigignore failed");
      exit (1);
    }

  posix_spawn_file_actions_t a;
  if (posix_spawn_file_actions_init (&a) != 0)
    {
      puts ("spawn_file_actions_init failed");
      exit (1);
    }

  if (posix_spawn_file_actions_adddup2 (&a, fd[1], STDOUT_FILENO) != 0)
    {
      puts ("spawn_file_actions_adddup2 failed");
      exit (1);
    }

  if (posix_spawn_file_actions_addclose (&a, fd[0]) != 0)
    {
      puts ("spawn_file_actions_addclose");
      exit (1);
    }

  pthread_t th;
  if (pthread_create (&th, NULL, tf, (void *) pthread_self ()) != 0)
    {
      puts ("create failed");
      exit (1);
    }

  pid_t pid;
  char *argv[] = { (char *) _PATH_BSHELL, (char *) "-c", (char *) "echo $$",
		   NULL };
  if (posix_spawn (&pid, _PATH_BSHELL, &a, NULL, argv, NULL) != 0)
    {
      puts ("spawn failed");
      exit (1);
    }

  close (fd[1]);

  char buf[200];
  ssize_t n;
  bool seen_pid = false;
  while (TEMP_FAILURE_RETRY ((n = read (fd[0], buf, sizeof (buf)))) > 0)
    {
      /* We only expect to read the PID.  */
      char *endp;
      long int rpid = strtol (buf, &endp, 10);

      if (*endp != '\n')
	{
	  printf ("didn't parse whole line: \"%s\"\n", buf);
	  exit (1);
	}
      if (endp == buf)
	{
	  puts ("read empty line");
	  exit (1);
	}

      if (rpid != pid)
	{
	  printf ("found \"%s\", expected PID %ld\n", buf, (long int) pid);
	  exit (1);
	}

      if (seen_pid)
	{
	  puts ("found more than one PID line");
	  exit (1);
	}

      seen_pid = true;
    }

  close (fd[0]);

  int status;
  int err = waitpid (pid, &status, 0);
  if (err != pid)
    {
      puts ("waitpid failed");
      exit (1);
    }

  if (!seen_pid)
    {
      puts ("didn't get PID");
      exit (1);
    }

  puts ("read correct PID");

  return 0;
}
void framebuffer_service(int fd, void *cookie)
{
    struct fbinfo fbinfo;
    unsigned int i, bsize;
    char buf[640];
    int fd_screencap;
    int w, h, f;
    int fds[2];

    if (pipe(fds) < 0) goto pipefail;

    pid_t pid = fork();
    if (pid < 0) goto done;

    if (pid == 0) {
        dup2(fds[1], STDOUT_FILENO);
        close(fds[0]);
        close(fds[1]);
        const char* command = "screencap";
        const char *args[2] = {command, NULL};
        execvp(command, (char**)args);
        exit(1);
    }

    fd_screencap = fds[0];

    /* read w, h & format */
    if(readx(fd_screencap, &w, 4)) goto done;
    if(readx(fd_screencap, &h, 4)) goto done;
    if(readx(fd_screencap, &f, 4)) goto done;

    fbinfo.version = DDMS_RAWIMAGE_VERSION;
    /* see hardware/hardware.h */
    switch (f) {
        case 1: /* RGBA_8888 */
            fbinfo.bpp = 32;
            fbinfo.size = w * h * 4;
            fbinfo.width = w;
            fbinfo.height = h;
            fbinfo.red_offset = 0;
            fbinfo.red_length = 8;
            fbinfo.green_offset = 8;
            fbinfo.green_length = 8;
            fbinfo.blue_offset = 16;
            fbinfo.blue_length = 8;
            fbinfo.alpha_offset = 24;
            fbinfo.alpha_length = 8;
            break;
        case 2: /* RGBX_8888 */
            fbinfo.bpp = 32;
            fbinfo.size = w * h * 4;
            fbinfo.width = w;
            fbinfo.height = h;
            fbinfo.red_offset = 0;
            fbinfo.red_length = 8;
            fbinfo.green_offset = 8;
            fbinfo.green_length = 8;
            fbinfo.blue_offset = 16;
            fbinfo.blue_length = 8;
            fbinfo.alpha_offset = 24;
            fbinfo.alpha_length = 0;
            break;
        case 3: /* RGB_888 */
            fbinfo.bpp = 24;
            fbinfo.size = w * h * 3;
            fbinfo.width = w;
            fbinfo.height = h;
            fbinfo.red_offset = 0;
            fbinfo.red_length = 8;
            fbinfo.green_offset = 8;
            fbinfo.green_length = 8;
            fbinfo.blue_offset = 16;
            fbinfo.blue_length = 8;
            fbinfo.alpha_offset = 24;
            fbinfo.alpha_length = 0;
            break;
        case 4: /* RGB_565 */
            fbinfo.bpp = 16;
            fbinfo.size = w * h * 2;
            fbinfo.width = w;
            fbinfo.height = h;
            fbinfo.red_offset = 11;
            fbinfo.red_length = 5;
            fbinfo.green_offset = 5;
            fbinfo.green_length = 6;
            fbinfo.blue_offset = 0;
            fbinfo.blue_length = 5;
            fbinfo.alpha_offset = 0;
            fbinfo.alpha_length = 0;
            break;
        case 5: /* BGRA_8888 */
            fbinfo.bpp = 32;
            fbinfo.size = w * h * 4;
            fbinfo.width = w;
            fbinfo.height = h;
            fbinfo.red_offset = 16;
            fbinfo.red_length = 8;
            fbinfo.green_offset = 8;
            fbinfo.green_length = 8;
            fbinfo.blue_offset = 0;
            fbinfo.blue_length = 8;
            fbinfo.alpha_offset = 24;
            fbinfo.alpha_length = 8;
           break;
        default:
            goto done;
    }

    /* write header */
    if(writex(fd, &fbinfo, sizeof(fbinfo))) goto done;

    /* write data */
    for(i = 0; i < fbinfo.size; i += bsize) {
      bsize = sizeof(buf);
      if (i + bsize > fbinfo.size)
        bsize = fbinfo.size - i;
      if(readx(fd_screencap, buf, bsize)) goto done;
      if(writex(fd, buf, bsize)) goto done;
    }

done:
    TEMP_FAILURE_RETRY(waitpid(pid, NULL, 0));

    close(fds[0]);
    close(fds[1]);
pipefail:
    close(fd);
}
コード例 #8
0
ファイル: ueventd.c プロジェクト: legionus/make-initrd
int
main(int argc, char **argv)
{
	struct timespec mtime = { 0 };
	sigset_t mask, sigmask_orig;
	int c, fd;
	int ep_timeout   = 0;
	int ignore_timer = 0;
	int new_events   = 0;

	char *eventdir, *prog, **prog_args;

	struct option long_options[] = {
		{ "help", no_argument, 0, 'h' },
		{ "version", no_argument, 0, 'V' },
		{ "foreground", no_argument, 0, 'f' },
		{ "loglevel", required_argument, 0, 'L' },
		{ "logfile", required_argument, 0, 'l' },
		{ "pidfile", required_argument, 0, 'p' },
		{ "timeout", required_argument, 0, 't' },
		{ 0, 0, 0, 0 }
	};

	while ((c = getopt_long(argc, argv, "hVfL:l:p:", long_options, NULL)) != -1) {
		switch (c) {
			case 't':
				timeout = atoi(optarg);
				if (!timeout)
					timeout = DEFAULT_TIMEOUT;
				break;
			case 'p':
				pidfile = optarg;
				break;
			case 'l':
				logfile = optarg;
				break;
			case 'L':
				log_priority = logging_level(optarg);
				break;
			case 'f':
				daemonize = 0;
				break;
			case 'V':
				printf("%s %s\n", PROGRAM_NAME, VERSION);
				return EXIT_SUCCESS;
			default:
			case 'h':
				printf("Usage: %s [options] DIRECTORY PROGRAM [ARGS...]\n"
				       "\nThe utility monitors the DIRECTORY and when\n"
				       "new files appear run the PROGRAM.\n\n"
				       "Options:\n"
				       " -p, --pidfile=FILE   pid file location;\n"
				       " -l, --logfile=FILE   log file;\n"
				       " -L, --loglevel=LVL   logging level;\n"
				       " -t, --timeout=SEC    number of seconds that need to wait"
				       "                      for files before the PROGRAM launch;\n"
				       " -f, --foreground     stay in the foreground;\n"
				       " -V, --version        print program version and exit;\n"
				       " -h, --help           show this text and exit.\n"
				       "\n",
				       PROGRAM_NAME);
				return EXIT_SUCCESS;
		}
	}

	if (optind >= argc)
		error(EXIT_FAILURE, 0, "You must specify the directory");

	eventdir = argv[optind++];

	if (optind >= argc)
		error(EXIT_FAILURE, 0, "You must specify the program");

	prog = canonicalize_file_name(argv[optind]);
	if (!prog)
		error(EXIT_FAILURE, errno, "Bad program");

	argv[optind] = strrchr(prog, '/');
	if (!argv[optind])
		argv[optind] = prog;

	prog_args = argv + optind;

	if (!log_priority)
		log_priority = logging_level("info");

	if (pidfile && check_pid(pidfile))
		error(EXIT_FAILURE, 0, "%s: already running", PROGRAM_NAME);

	if (chdir("/") < 0)
		error(EXIT_FAILURE, errno, "%s: chdir(/)", PROGRAM_NAME);

	close(STDIN_FILENO);

	if ((fd = open("/dev/null", O_RDONLY)) < 0)
		error(EXIT_FAILURE, errno, "%s: open(/dev/null)", PROGRAM_NAME);

	if (fd != STDIN_FILENO) {
		dup2(fd, STDIN_FILENO);
		close(fd);
	}

	if (daemonize && daemon(0, 1) < 0)
		error(EXIT_FAILURE, errno, "%s: daemon", PROGRAM_NAME);

	logging_init();

	info("starting version %s", VERSION);

	if (pidfile && write_pid(pidfile) == 0)
		return EXIT_FAILURE;

	sigfillset(&mask);
	sigprocmask(SIG_SETMASK, &mask, &sigmask_orig);

	sigdelset(&mask, SIGABRT);
	sigdelset(&mask, SIGSEGV);

	if ((fd_ep = epoll_create1(EPOLL_CLOEXEC)) < 0)
		fatal("epoll_create1: %m");

	if ((fd_signal = signalfd(-1, &mask, SFD_NONBLOCK | SFD_CLOEXEC)) < 0)
		fatal("signalfd: %m");

	epollin_add(fd_ep, fd_signal);

	if ((fd_eventdir = inotify_init1(IN_NONBLOCK | IN_CLOEXEC)) < 0)
		fatal("inotify_init1: %m");

	if (inotify_add_watch(fd_eventdir, eventdir, IN_ONLYDIR | IN_DONT_FOLLOW | IN_MOVED_TO | IN_CLOSE_WRITE) < 0)
		fatal("inotify_add_watch: %m");

	epollin_add(fd_ep, fd_eventdir);

	ignore_timer = is_dir_not_empty(eventdir);

	if (clock_gettime(CLOCK_MONOTONIC, &now) < 0)
		fatal("clock_gettime: %m");
	last.tv_sec = now.tv_sec;

	while (!do_exit) {
		struct epoll_event ev[42];
		int i, fdcount;
		ssize_t size;

		if ((fdcount = epoll_wait(fd_ep, ev, ARRAY_SIZE(ev), ep_timeout)) < 0)
			continue;

		if (!ep_timeout)
			ep_timeout = timeout * 1000;

		for (i = 0; i < fdcount; i++) {

			if (!(ev[i].events & EPOLLIN)) {
				continue;

			} else if (ev[i].data.fd == fd_signal) {
				struct signalfd_siginfo fdsi;

				size = TEMP_FAILURE_RETRY(read(fd_signal,
				                               &fdsi, sizeof(struct signalfd_siginfo)));

				if (size != sizeof(struct signalfd_siginfo)) {
					err("unable to read signal info");
					continue;
				}

				handle_signal(fdsi.ssi_signo);

			} else if (ev[i].data.fd == fd_eventdir) {
				read_inotify_events(fd_eventdir);
				new_events += 1;
			}
		}

		if (new_events) {
			struct stat sb;

			new_events = 0;

			if (lstat(eventdir, &sb) < 0)
				fatal("lstat: %s: %m", eventdir);

			if (mtime.tv_sec != sb.st_mtim.tv_sec || mtime.tv_nsec != sb.st_mtim.tv_nsec) {
				if (clock_gettime(CLOCK_MONOTONIC, &now) < 0)
					fatal("clock_gettime: %m");
				last.tv_sec = now.tv_sec;
			}

			mtime.tv_sec  = sb.st_mtim.tv_sec;
			mtime.tv_nsec = sb.st_mtim.tv_nsec;
		}

		if (worker_pid)
			continue;

		if (!ignore_timer) {
			if (clock_gettime(CLOCK_MONOTONIC, &now) < 0)
				fatal("clock_gettime: %m");

			if (now.tv_sec < last.tv_sec || (now.tv_sec - last.tv_sec) < timeout)
				continue;
		}
		ignore_timer = 0;

		if ((worker_pid = spawn_worker(prog, prog_args)) < 0)
			fatal("spawn_worker: %m");

		dbg("Run worker %d", worker_pid);
	}

	epollin_remove(fd_ep, fd_signal);
	epollin_remove(fd_ep, fd_eventdir);

	free(prog);

	if (pidfile)
		remove_pid(pidfile);

	logging_close();

	return EXIT_SUCCESS;
}
コード例 #9
0
static void SIGCHLD_handler(int) {
    if (TEMP_FAILURE_RETRY(write(signal_write_fd, "1", 1)) == -1) {
        PLOG(ERROR) << "write(signal_write_fd) failed";
    }
}
コード例 #10
0
ファイル: tst-stackguard1.c プロジェクト: cmjonze/eglibc_svn
static int
do_test (void)
{
    if (!stack_chk_guard_copy_set)
    {
        puts ("constructor has not been run");
        return 1;
    }

    if (stack_chk_guard_copy != STACK_CHK_GUARD)
    {
        puts ("STACK_CHK_GUARD changed between constructor and do_test");
        return 1;
    }

    if (child)
    {
        write (2, &stack_chk_guard_copy, sizeof (stack_chk_guard_copy));
        return 0;
    }

    if (command == NULL)
    {
        puts ("missing --command or --child argument");
        return 1;
    }

#define N 16
    uintptr_t child_stack_chk_guards[N + 1];
    child_stack_chk_guards[N] = stack_chk_guard_copy;
    int i;
    for (i = 0; i < N; ++i)
    {
        if (pipe (fds) < 0)
        {
            printf ("couldn't create pipe: %m\n");
            return 1;
        }

        pid_t pid = fork ();
        if (pid < 0)
        {
            printf ("fork failed: %m\n");
            return 1;
        }

        if (!pid)
        {
            if (stack_chk_guard_copy != STACK_CHK_GUARD)
            {
                puts ("STACK_CHK_GUARD changed after fork");
                exit (1);
            }

            close (fds[0]);
            close (2);
            dup2 (fds[1], 2);
            close (fds[1]);

            system (command);
            exit (0);
        }

        close (fds[1]);

        if (TEMP_FAILURE_RETRY (read (fds[0], &child_stack_chk_guards[i],
                                      sizeof (uintptr_t))) != sizeof (uintptr_t))
        {
            puts ("could not read stack_chk_guard value from child");
            return 1;
        }

        close (fds[0]);

        pid_t termpid;
        int status;
        termpid = TEMP_FAILURE_RETRY (waitpid (pid, &status, 0));
        if (termpid == -1)
        {
            printf ("waitpid failed: %m\n");
            return 1;
        }
        else if (termpid != pid)
        {
            printf ("waitpid returned %ld != %ld\n",
                    (long int) termpid, (long int) pid);
            return 1;
        }
        else if (!WIFEXITED (status) || WEXITSTATUS (status))
        {
            puts ("child hasn't exited with exit status 0");
            return 1;
        }
    }

    qsort (child_stack_chk_guards, N + 1, sizeof (uintptr_t), uintptr_t_cmp);

    uintptr_t default_guard = 0;
    unsigned char *p = (unsigned char *) &default_guard;
    p[sizeof (uintptr_t) - 1] = 255;
    p[sizeof (uintptr_t) - 2] = '\n';
    p[0] = 0;

    /* Test if the stack guard canaries are either randomized,
       or equal to the default stack guard canary value.
       Even with randomized stack guards it might happen
       that the random number generator generates the same
       values, but if that happens in more than half from
       the 16 runs, something is very wrong.  */
    int ndifferences = 0;
    int ndefaults = 0;
    for (i = 0; i < N; ++i)
    {
        if (child_stack_chk_guards[i] != child_stack_chk_guards[i+1])
            ndifferences++;
        else if (child_stack_chk_guards[i] == default_guard)
            ndefaults++;
    }

    printf ("differences %d defaults %d\n", ndifferences, ndefaults);

    if (ndifferences < N / 2 && ndefaults < N / 2)
    {
        puts ("stack guard canaries are not randomized enough");
        puts ("nor equal to the default canary value");
        return 1;
    }

    return 0;
}
コード例 #11
0
ファイル: tst-tls2.c プロジェクト: Xilinx/eglibc
int
do_test (void)
{
  if (pthread_barrier_init (&b, NULL, N + 1) != 0)
    {
      puts ("barrier_init failed");
      exit (1);
    }

  if (sem_init (&s, 0, 0) != 0)
    {
      puts ("sem_init failed");
      exit (1);
    }

  struct sigaction sa;
  sa.sa_handler = handler;
  sigemptyset (&sa.sa_mask);
  sa.sa_flags = 0;
  if (sigaction (THE_SIG, &sa, NULL) != 0)
    {
      puts ("sigaction failed");
      exit (1);
    }

  pthread_attr_t a;

  if (pthread_attr_init (&a) != 0)
    {
      puts ("attr_init failed");
      exit (1);
    }

  if (pthread_attr_setstacksize (&a, 1 * 1024 * 1024) != 0)
    {
      puts ("attr_setstacksize failed");
      return 1;
    }

  int i;
  for (i = 0; i < N; ++i)
    if (pthread_create (&th[i], &a, tf, cbs[i]) != 0)
      {
	puts ("pthread_create failed");
	exit (1);
      }

  if (pthread_attr_destroy (&a) != 0)
    {
      puts ("attr_destroy failed");
      exit (1);
    }

  pthread_barrier_wait (&b);

  sigset_t ss;
  sigemptyset (&ss);
  sigaddset (&ss, THE_SIG);
  if (pthread_sigmask (SIG_BLOCK, &ss, NULL) != 0)
    {
      puts ("pthread_sigmask failed");
      exit (1);
    }

  /* Start sending signals.  */
  for (i = 0; i < TOTAL_SIGS; ++i)
    {
      if (kill (getpid (), THE_SIG) != 0)
	{
	  puts ("kill failed");
	  exit (1);
	}

      if (TEMP_FAILURE_RETRY (sem_wait (&s)) != 0)
	{
	  puts ("sem_wait failed");
	  exit (1);
	}

      ++nsigs;
    }

  pthread_barrier_wait (&b);

  for (i = 0; i < N; ++i)
    if (pthread_join (th[i], NULL) != 0)
      {
	puts ("join failed");
	exit (1);
      }

  return 0;
}
コード例 #12
0
static void handle_property_set_fd()
{
    prop_msg msg;
    int s;
    int r;
    struct ucred cr;
    struct sockaddr_un addr;
    socklen_t addr_size = sizeof(addr);
    socklen_t cr_size = sizeof(cr);
    char * source_ctx = NULL;
    struct pollfd ufds[1];
    const int timeout_ms = 2 * 1000;  /* Default 2 sec timeout for caller to send property. */
    int nr;

    if ((s = accept(property_set_fd, (struct sockaddr *) &addr, &addr_size)) < 0) {
        return;
    }

    /* Check socket options here */
    if (getsockopt(s, SOL_SOCKET, SO_PEERCRED, &cr, &cr_size) < 0) {
        close(s);
        ERROR("Unable to receive socket options\n");
        return;
    }

    ufds[0].fd = s;
    ufds[0].events = POLLIN;
    ufds[0].revents = 0;
    nr = TEMP_FAILURE_RETRY(poll(ufds, 1, timeout_ms));
    if (nr == 0) {
        ERROR("sys_prop: timeout waiting for uid=%d to send property message.\n", cr.uid);
        close(s);
        return;
    } else if (nr < 0) {
        ERROR("sys_prop: error waiting for uid=%d to send property message: %s\n", cr.uid, strerror(errno));
        close(s);
        return;
    }

    r = TEMP_FAILURE_RETRY(recv(s, &msg, sizeof(msg), MSG_DONTWAIT));
    if(r != sizeof(prop_msg)) {
        ERROR("sys_prop: mis-match msg size received: %d expected: %zu: %s\n",
              r, sizeof(prop_msg), strerror(errno));
        close(s);
        return;
    }

    switch(msg.cmd) {
    case PROP_MSG_SETPROP:
        msg.name[PROP_NAME_MAX-1] = 0;
        msg.value[PROP_VALUE_MAX-1] = 0;

        if (!is_legal_property_name(msg.name, strlen(msg.name))) {
            ERROR("sys_prop: illegal property name. Got: \"%s\"\n", msg.name);
            close(s);
            return;
        }

        getpeercon(s, &source_ctx);

        if(memcmp(msg.name,"ctl.",4) == 0) {
            // Keep the old close-socket-early behavior when handling
            // ctl.* properties.
            close(s);
            if (check_control_mac_perms(msg.value, source_ctx, &cr)) {
                handle_control_message((char*) msg.name + 4, (char*) msg.value);
            } else {
                ERROR("sys_prop: Unable to %s service ctl [%s] uid:%d gid:%d pid:%d\n",
                        msg.name + 4, msg.value, cr.uid, cr.gid, cr.pid);
            }
        } else {
            if (check_perms(msg.name, source_ctx, &cr)) {
                property_set((char*) msg.name, (char*) msg.value);
            } else {
                ERROR("sys_prop: permission denied uid:%d  name:%s\n",
                      cr.uid, msg.name);
            }

            // Note: bionic's property client code assumes that the
            // property server will not close the socket until *AFTER*
            // the property is written to memory.
            close(s);
        }
        freecon(source_ctx);
        break;

    default:
        close(s);
        break;
    }
}
コード例 #13
0
ファイル: player.c プロジェクト: janisz/unix
void disconnectPlayer(Player *player)
{
	if (fd_is_valid(player->descriptor))
		if(TEMP_FAILURE_RETRY(close(player->descriptor))<0)ERR("close");
}
コード例 #14
0
ファイル: tst-sem3.c プロジェクト: Drakey83/steamlink-sdk
int
main (void)
{
  size_t ps = sysconf (_SC_PAGESIZE);
  char tmpfname[] = "/tmp/tst-sem3.XXXXXX";
  char data[ps];
  void *mem;
  int fd;
  sem_t *s;
  pid_t pid;
  char *p;

  fd = mkstemp (tmpfname);
  if (fd == -1)
    {
      printf ("cannot open temporary file: %m\n");
      exit (1);
    }

  /* Make sure it is always removed.  */
  unlink (tmpfname);

  /* Create one page of data.  */
  memset (data, '\0', ps);

  /* Write the data to the file.  */
  if (write (fd, data, ps) != (ssize_t) ps)
    {
      puts ("short write");
      exit (1);
    }

  mem = mmap (NULL, ps, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
  if (mem == MAP_FAILED)
    {
      printf ("mmap failed: %m\n");
      exit (1);
    }

  s = (sem_t *) (((uintptr_t) mem + __alignof (sem_t))
		 & ~(__alignof (sem_t) - 1));
  p = (char *) (s + 1);

  if (sem_init (s, 1, 1) == -1)
    {
      puts ("init failed");
      exit (1);
    }

  if (TEMP_FAILURE_RETRY (sem_wait (s)) == -1)
    {
      puts ("1st wait failed");
      exit (1);
    }

  errno = 0;
  if (TEMP_FAILURE_RETRY (sem_trywait (s)) != -1)
    {
      puts ("trywait succeeded");
      exit (1);
    }
  else if (errno != EAGAIN)
    {
      puts ("trywait didn't return EAGAIN");
      exit (1);
    }

  *p = 0;

  puts ("going to fork now");
  pid = fork ();
  if (pid == -1)
    {
      puts ("fork failed");
      exit (1);
    }
  else if (pid == 0)
    {
      /* Play some lock ping-pong.  It's our turn to unlock first.  */
      if ((*p)++ != 0)
	{
	  puts ("child: *p != 0");
	  exit (1);
	}

      if (sem_post (s) == -1)
	{
	  puts ("child: 1st post failed");
	  exit (1);
	}

      puts ("child done");
    }
  else
    {
      if (TEMP_FAILURE_RETRY (sem_wait (s)) == -1)
	{
	  printf ("parent: 2nd wait failed: %m\n");
	  exit (1);
	}

      if (*p != 1)
	{
	  puts ("*p != 1");
	  exit (1);
	}

      puts ("parent done");
    }

  exit (0);
}
コード例 #15
0
ファイル: tst-mutex9.c プロジェクト: AubrCool/glibc
static int
do_test (void)
{
  size_t ps = sysconf (_SC_PAGESIZE);
  char tmpfname[] = "/tmp/tst-mutex9.XXXXXX";
  char data[ps];
  void *mem;
  int fd;
  pthread_mutex_t *m;
  pthread_mutexattr_t a;
  pid_t pid;

  fd = mkstemp (tmpfname);
  if (fd == -1)
    {
      printf ("cannot open temporary file: %m\n");
      return 1;
    }

  /* Make sure it is always removed.  */
  unlink (tmpfname);

  /* Create one page of data.  */
  memset (data, '\0', ps);

  /* Write the data to the file.  */
  if (write (fd, data, ps) != (ssize_t) ps)
    {
      puts ("short write");
      return 1;
    }

  mem = mmap (NULL, ps, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
  if (mem == MAP_FAILED)
    {
      printf ("mmap failed: %m\n");
      return 1;
    }

  m = (pthread_mutex_t *) (((uintptr_t) mem + __alignof (pthread_mutex_t))
			   & ~(__alignof (pthread_mutex_t) - 1));

  if (pthread_mutexattr_init (&a) != 0)
    {
      puts ("mutexattr_init failed");
      return 1;
    }

  if (pthread_mutexattr_setpshared (&a, PTHREAD_PROCESS_SHARED) != 0)
    {
      puts ("mutexattr_setpshared failed");
      return 1;
    }

  if (pthread_mutexattr_settype (&a, PTHREAD_MUTEX_RECURSIVE) != 0)
    {
      puts ("mutexattr_settype failed");
      return 1;
    }

#ifdef ENABLE_PI
  if (pthread_mutexattr_setprotocol (&a, PTHREAD_PRIO_INHERIT) != 0)
    {
      puts ("pthread_mutexattr_setprotocol failed");
      return 1;
    }
#endif

  int e;
  if ((e = pthread_mutex_init (m, &a)) != 0)
    {
#ifdef ENABLE_PI
      if (e == ENOTSUP)
	{
	  puts ("PI mutexes unsupported");
	  return 0;
	}
#endif
      puts ("mutex_init failed");
      return 1;
    }

  if (pthread_mutex_lock (m) != 0)
    {
      puts ("mutex_lock failed");
      return 1;
    }

  if (pthread_mutexattr_destroy (&a) != 0)
    {
      puts ("mutexattr_destroy failed");
      return 1;
    }

  puts ("going to fork now");
  pid = fork ();
  if (pid == -1)
    {
      puts ("fork failed");
      return 1;
    }
  else if (pid == 0)
    {
      if (pthread_mutex_trylock (m) == 0)
	{
	  puts ("child: mutex_trylock succeeded");
	  exit (1);
	}

      if (pthread_mutex_unlock (m) == 0)
	{
	  puts ("child: mutex_unlock succeeded");
	  exit (1);
	}

      struct timeval tv;
      gettimeofday (&tv, NULL);
      struct timespec ts;
      TIMEVAL_TO_TIMESPEC (&tv, &ts);
      ts.tv_nsec += 500000000;
      if (ts.tv_nsec >= 1000000000)
	{
	  ++ts.tv_sec;
	  ts.tv_nsec -= 1000000000;
	}

      e = pthread_mutex_timedlock (m, &ts);
      if (e == 0)
	{
	  puts ("child: mutex_timedlock succeeded");
	  exit (1);
	}
      if (e != ETIMEDOUT)
	{
	  puts ("child: mutex_timedlock didn't time out");
	  exit (1);
	}

      alarm (1);

      pthread_mutex_lock (m);

      puts ("child: mutex_lock returned");

      exit (0);
    }

  sleep (2);

  int status;
  if (TEMP_FAILURE_RETRY (waitpid (pid, &status, 0)) != pid)
    {
      puts ("waitpid failed");
      return 1;
    }
  if (! WIFSIGNALED (status))
    {
      puts ("child not killed by signal");
      return 1;
    }
  if (WTERMSIG (status) != SIGALRM)
    {
      puts ("child not killed by SIGALRM");
      return 1;
    }

  return 0;
}
コード例 #16
0
ファイル: DBusThread.cpp プロジェクト: Pulfer/Pale-Moon
  NS_IMETHOD Run()
  {
    MOZ_ASSERT(!NS_IsMainThread());

    bool exitThread = false;

    while (!exitThread) {

      int res = TEMP_FAILURE_RETRY(poll(mConnection->mPollData.Elements(),
                                        mConnection->mPollData.Length(),
                                        -1));
      NS_ENSURE_TRUE(res > 0, NS_OK);

      nsTArray<pollfd>::size_type i = 0;

      while (i < mConnection->mPollData.Length()) {
        if (mConnection->mPollData[i].revents == POLLIN) {

          if (mConnection->mPollData[i].fd == mConnection->mControlFdR.get()) {
            char data;
            res = TEMP_FAILURE_RETRY(read(mConnection->mControlFdR.get(), &data, sizeof(data)));
            NS_ENSURE_TRUE(res > 0, NS_OK);

            switch (data) {
            case DBUS_EVENT_LOOP_EXIT:
              exitThread = true;
              break;
            case DBUS_EVENT_LOOP_ADD:
              HandleWatchAdd(mConnection);
              break;
            case DBUS_EVENT_LOOP_REMOVE:
              HandleWatchRemove(mConnection);
              // don't increment i, or we'll skip one element
              continue;
            case DBUS_EVENT_LOOP_WAKEUP:
              NS_ProcessPendingEvents(NS_GetCurrentThread(),
                                      PR_INTERVAL_NO_TIMEOUT);
              break;
            default:
#if DEBUG
              nsCString warning("unknown command ");
              warning.AppendInt(data);
              NS_WARNING(warning.get());
#endif
              break;
            }
          } else {
            short events = mConnection->mPollData[i].revents;
            unsigned int flags = UnixEventsToDBusFlags(events);
            dbus_watch_handle(mConnection->mWatchData[i], flags);
            mConnection->mPollData[i].revents = 0;
            // Break at this point since we don't know if the operation
            // was destructive
            break;
          }
          while (dbus_connection_dispatch(mConnection->GetConnection()) ==
                 DBUS_DISPATCH_DATA_REMAINS)
          {}
        }
        ++i;
      }
    }

    return NS_OK;
  }
コード例 #17
0
int
internal_function
__libdwfl_open_by_build_id (Dwfl_Module *mod, bool debug, char **file_name)
{
    /* If *FILE_NAME was primed into the module, leave it there
       as the fallback when we have nothing to offer.  */
    errno = 0;
    if (mod->build_id_len <= 0)
        return -1;

    const size_t id_len = mod->build_id_len;
    const uint8_t *id = mod->build_id_bits;

    /* Search debuginfo_path directories' .build-id/ subdirectories.  */

    char id_name[sizeof "/.build-id/" + 1 + id_len * 2 + sizeof ".debug" - 1];
    strcpy (id_name, "/.build-id/");
    int n = snprintf (&id_name[sizeof "/.build-id/" - 1],
                      4, "%02" PRIx8 "/", (uint8_t) id[0]);
    assert (n == 3);
    for (size_t i = 1; i < id_len; ++i)
    {
        n = snprintf (&id_name[sizeof "/.build-id/" - 1 + 3 + (i - 1) * 2],
                      3, "%02" PRIx8, (uint8_t) id[i]);
        assert (n == 2);
    }
    if (debug)
        strcpy (&id_name[sizeof "/.build-id/" - 1 + 3 + (id_len - 1) * 2],
                ".debug");

    const Dwfl_Callbacks *const cb = mod->dwfl->callbacks;

    /* ANDROID_CHANGE_BEGIN */
#if defined(__BIONIC__) || defined(__APPLE__)
    char *path = strdup ((cb->debuginfo_path ? *cb->debuginfo_path : NULL)
                         ?: DEFAULT_DEBUGINFO_PATH);
#else
    char *path = strdupa ((cb->debuginfo_path ? *cb->debuginfo_path : NULL)
                          ?: DEFAULT_DEBUGINFO_PATH);
#endif
    /* ANDROID_CHANGE_END */

    int fd = -1;
    char *dir;
    while (fd < 0 && (dir = strsep (&path, ":")) != NULL)
    {
        if (dir[0] == '+' || dir[0] == '-')
            ++dir;

        /* Only absolute directory names are useful to us.  */
        if (dir[0] != '/')
            continue;

        size_t dirlen = strlen (dir);
        char *name = malloc (dirlen + sizeof id_name);
        if (unlikely (name == NULL))
            break;
        memcpy (mempcpy (name, dir, dirlen), id_name, sizeof id_name);
        fd = TEMP_FAILURE_RETRY (open64 (name, O_RDONLY));
        if (fd >= 0)
        {
            if (*file_name != NULL)
                free (*file_name);
            *file_name = canonicalize_file_name (name);
            if (*file_name == NULL)
            {
                *file_name = name;
                name = NULL;
            }
        }
        free (name);
    }

    /* ANDROID_CHANGE_BEGIN */
#ifdef __BIONIC__
    free(path);
#endif
    /* ANDROID_CHANGE_END */

    /* If we simply found nothing, clear errno.  If we had some other error
       with the file, report that.  Possibly this should treat other errors
       like ENOENT too.  But ignoring all errors could mask some that should
       be reported.  */
    if (fd < 0 && errno == ENOENT)
        errno = 0;

    return fd;
}
コード例 #18
0
static int read_request(int fd, debugger_request_t* out_request) {
  ucred cr;
  socklen_t len = sizeof(cr);
  int status = getsockopt(fd, SOL_SOCKET, SO_PEERCRED, &cr, &len);
  if (status != 0) {
    ALOGE("cannot get credentials");
    return -1;
  }

  ALOGV("reading tid");
  fcntl(fd, F_SETFL, O_NONBLOCK);

  pollfd pollfds[1];
  pollfds[0].fd = fd;
  pollfds[0].events = POLLIN;
  pollfds[0].revents = 0;
  status = TEMP_FAILURE_RETRY(poll(pollfds, 1, 3000));
  if (status != 1) {
    ALOGE("timed out reading tid (from pid=%d uid=%d)\n", cr.pid, cr.uid);
    return -1;
  }

  debugger_msg_t msg;
  memset(&msg, 0, sizeof(msg));
  status = TEMP_FAILURE_RETRY(read(fd, &msg, sizeof(msg)));
  if (status < 0) {
    ALOGE("read failure? %s (pid=%d uid=%d)\n", strerror(errno), cr.pid, cr.uid);
    return -1;
  }
  if (status != sizeof(debugger_msg_t)) {
    ALOGE("invalid crash request of size %d (from pid=%d uid=%d)\n", status, cr.pid, cr.uid);
    return -1;
  }

  out_request->action = static_cast<debugger_action_t>(msg.action);
  out_request->tid = msg.tid;
  out_request->pid = cr.pid;
  out_request->uid = cr.uid;
  out_request->gid = cr.gid;
  out_request->abort_msg_address = msg.abort_msg_address;
  out_request->original_si_code = msg.original_si_code;

  if (msg.action == DEBUGGER_ACTION_CRASH) {
    // Ensure that the tid reported by the crashing process is valid.
    char buf[64];
    struct stat s;
    snprintf(buf, sizeof buf, "/proc/%d/task/%d", out_request->pid, out_request->tid);
    if (stat(buf, &s)) {
      ALOGE("tid %d does not exist in pid %d. ignoring debug request\n",
          out_request->tid, out_request->pid);
      return -1;
    }
  } else if (cr.uid == 0
            || (cr.uid == AID_SYSTEM && msg.action == DEBUGGER_ACTION_DUMP_BACKTRACE)) {
    // Only root or system can ask us to attach to any process and dump it explicitly.
    // However, system is only allowed to collect backtraces but cannot dump tombstones.
    status = get_process_info(out_request->tid, &out_request->pid,
                              &out_request->uid, &out_request->gid);
    if (status < 0) {
      ALOGE("tid %d does not exist. ignoring explicit dump request\n", out_request->tid);
      return -1;
    }

    if (!selinux_action_allowed(fd, out_request))
      return -1;
  } else {
    // No one else is allowed to dump arbitrary processes.
    return -1;
  }
  return 0;
}
コード例 #19
0
static int statsdWrite(struct timespec* ts, struct iovec* vec, size_t nr) {
    ssize_t ret;
    int sock;
    static const unsigned headerLength = 1;
    struct iovec newVec[nr + headerLength];
    android_log_header_t header;
    size_t i, payloadSize;

    sock = atomic_load(&statsdLoggerWrite.sock);
    if (sock < 0) switch (sock) {
            case -ENOTCONN:
            case -ECONNREFUSED:
            case -ENOENT:
                break;
            default:
                return -EBADF;
        }
    /*
     *  struct {
     *      // what we provide to socket
     *      android_log_header_t header;
     *      // caller provides
     *      union {
     *          struct {
     *              char     prio;
     *              char     payload[];
     *          } string;
     *          struct {
     *              uint32_t tag
     *              char     payload[];
     *          } binary;
     *      };
     *  };
     */

    header.tid = gettid();
    header.realtime.tv_sec = ts->tv_sec;
    header.realtime.tv_nsec = ts->tv_nsec;

    newVec[0].iov_base = (unsigned char*)&header;
    newVec[0].iov_len = sizeof(header);

    // If we dropped events before, try to tell statsd.
    if (sock >= 0) {
        int32_t snapshot = atomic_exchange_explicit(&dropped, 0, memory_order_relaxed);
        if (snapshot) {
            android_log_event_long_t buffer;
            header.id = LOG_ID_STATS;
            // store the last log error in the tag field. This tag field is not used by statsd.
            buffer.header.tag = htole32(atomic_load(&log_error));
            buffer.payload.type = EVENT_TYPE_LONG;
            // format:
            // |atom_tag|dropped_count|
            int64_t composed_long = atomic_load(&atom_tag);
            // Send 2 int32's via an int64.
            composed_long = ((composed_long << 32) | ((int64_t)snapshot));
            buffer.payload.data = htole64(composed_long);

            newVec[headerLength].iov_base = &buffer;
            newVec[headerLength].iov_len = sizeof(buffer);

            ret = TEMP_FAILURE_RETRY(writev(sock, newVec, 2));
            if (ret != (ssize_t)(sizeof(header) + sizeof(buffer))) {
                atomic_fetch_add_explicit(&dropped, snapshot, memory_order_relaxed);
            }
        }
    }

    header.id = LOG_ID_STATS;

    for (payloadSize = 0, i = headerLength; i < nr + headerLength; i++) {
        newVec[i].iov_base = vec[i - headerLength].iov_base;
        payloadSize += newVec[i].iov_len = vec[i - headerLength].iov_len;

        if (payloadSize > LOGGER_ENTRY_MAX_PAYLOAD) {
            newVec[i].iov_len -= payloadSize - LOGGER_ENTRY_MAX_PAYLOAD;
            if (newVec[i].iov_len) {
                ++i;
            }
            break;
        }
    }

    /*
     * The write below could be lost, but will never block.
     *
     * ENOTCONN occurs if statsd has died.
     * ENOENT occurs if statsd is not running and socket is missing.
     * ECONNREFUSED occurs if we can not reconnect to statsd.
     * EAGAIN occurs if statsd is overloaded.
     */
    if (sock < 0) {
        ret = sock;
    } else {
        ret = TEMP_FAILURE_RETRY(writev(sock, newVec, i));
        if (ret < 0) {
            ret = -errno;
        }
    }
    switch (ret) {
        case -ENOTCONN:
        case -ECONNREFUSED:
        case -ENOENT:
            if (statd_writer_trylock()) {
                return ret; /* in a signal handler? try again when less stressed
                             */
            }
            __statsdClose(ret);
            ret = statsdOpen();
            statsd_writer_init_unlock();

            if (ret < 0) {
                return ret;
            }

            ret = TEMP_FAILURE_RETRY(writev(atomic_load(&statsdLoggerWrite.sock), newVec, i));
            if (ret < 0) {
                ret = -errno;
            }
        /* FALLTHRU */
        default:
            break;
    }

    if (ret > (ssize_t)sizeof(header)) {
        ret -= sizeof(header);
    }

    return ret;
}
コード例 #20
0
// A function used to determine at runtime if the target CPU supports
// the ARM NEON instruction set. This implementation is Linux-specific.
static bool sk_cpu_arm_check_neon(void) {
    // If we fail any of the following, assume we don't have NEON instructions
    // This allows us to return immediately in case of error.
    bool result = false;

// Use the Android NDK's cpu-features helper library to detect NEON at runtime.
// See http://crbug.com/164154 to see why this is needed in Chromium for Android.
#ifdef SK_BUILD_FOR_ANDROID

  result = (android_getCpuFeatures() & ANDROID_CPU_ARM_FEATURE_NEON) != 0;

#else  // SK_BUILD_FOR_ANDROID

    // There is no user-accessible CPUID instruction on ARM that we can use.
    // Instead, we must parse /proc/cpuinfo and look for the 'neon' feature.
    // For example, here's a typical output (Nexus S running ICS 4.0.3):
    /*
    Processor       : ARMv7 Processor rev 2 (v7l)
    BogoMIPS        : 994.65
    Features        : swp half thumb fastmult vfp edsp thumbee neon vfpv3
    CPU implementer : 0x41
    CPU architecture: 7
    CPU variant     : 0x2
    CPU part        : 0xc08
    CPU revision    : 2

    Hardware        : herring
    Revision        : 000b
    Serial          : 3833c77d6dc000ec
    */
    char   buffer[4096];

    do {
        // open /proc/cpuinfo
        int fd = TEMP_FAILURE_RETRY(open("/proc/cpuinfo", O_RDONLY));
        if (fd < 0) {
            SkDebugf("Could not open /proc/cpuinfo: %s\n", strerror(errno));
            break;
        }

        // Read the file. To simplify our search, we're going to place two
        // sentinel '\n' characters: one at the start of the buffer, and one at
        // the end. This means we reserve the first and last buffer bytes.
        buffer[0] = '\n';
        int size = TEMP_FAILURE_RETRY(read(fd, buffer+1, sizeof(buffer)-2));
        close(fd);

        if (size < 0) {  // should not happen
            SkDebugf("Could not read /proc/cpuinfo: %s\n", strerror(errno));
            break;
        }

        SkDebugf("START /proc/cpuinfo:\n%.*s\nEND /proc/cpuinfo\n",
                 size, buffer+1);

        // Compute buffer limit, and place final sentinel
        char* buffer_end = buffer + 1 + size;
        buffer_end[0] = '\n';

        // Now, find a line that starts with "Features", i.e. look for
        // '\nFeatures ' in our buffer.
        const char features[] = "\nFeatures\t";
        const size_t features_len = sizeof(features)-1;

        char*  line = (char*) memmem(buffer, buffer_end - buffer,
                                     features, features_len);
        if (line == nullptr) {  // Weird, no Features line, bad kernel?
            SkDebugf("Could not find a line starting with 'Features'"
              "in /proc/cpuinfo ?\n");
            break;
        }

        line += features_len;  // Skip the "\nFeatures\t" prefix

        // Find the end of the current line
        char* line_end = (char*) memchr(line, '\n', buffer_end - line);
        if (line_end == nullptr)
            line_end = buffer_end;

        // Now find an instance of 'neon' in the flags list. We want to
        // ensure it's only 'neon' and not something fancy like 'noneon'
        // so check that it follows a space.
        const char neon[] = " neon";
        const size_t neon_len = sizeof(neon)-1;
        const char* flag = (const char*) memmem(line, line_end - line,
                                                neon, neon_len);
        if (flag == nullptr)
            break;

        // Ensure it is followed by a space or a newline.
        if (flag[neon_len] != ' ' && flag[neon_len] != '\n')
            break;

        // Fine, we support Arm NEON !
        result = true;

    } while (0);

#endif  // SK_BUILD_FOR_ANDROID

    if (result) {
        SkDEBUGF(("Device supports ARM NEON instructions!\n"));
    } else {
        SkDEBUGF(("Device does NOT support ARM NEON instructions!\n"));
    }
    return result;
}
コード例 #21
0
ファイル: mce.c プロジェクト: oleid/mce
/** Signal handler callback for writing signals to pipe
 *
 * @param sig the signal number to pass to mainloop via pipe
 */
static void mce_tx_signal_cb(int sig)
{
	/* NOTE: this function must be kept async-signal-safe! */

	static volatile int exit_tries = 0;

	static const char msg[] = "\n*** BREAK ***\n";
#ifdef ENABLE_WAKELOCKS
	static const char die[] = "\n*** UNRECOVERABLE FAILURE ***\n";
#endif

	/* FIXME: Should really use sigaction() to avoid having
	 * the default handler active until we manage to restore
	 * our handler here ... */
	signal(sig, mce_tx_signal_cb);

	switch( sig )
	{
	case SIGINT:
	case SIGQUIT:
	case SIGTERM:
		/* Make sure that a stuck or non-existing mainloop does
		 * not stop us from handling at least repeated terminating
		 signals ... */

#ifdef ENABLE_WAKELOCKS
		/* We are on exit path -> block suspend for good */
		wakelock_block_suspend_until_exit();
#endif

		no_error_check_write(STDERR_FILENO, msg, sizeof msg - 1);

		if( !mainloop || ++exit_tries >= 2 ) {
			mce_abort();
		}
		break;

#ifdef ENABLE_WAKELOCKS
	case SIGABRT:
	case SIGILL:
	case SIGFPE:
	case SIGSEGV:
	case SIGALRM:
	case SIGBUS:
		/* Unrecoverable failures can't be handled in the mainloop
		 * Terminate but disable suspend first */
		no_error_check_write(STDERR_FILENO, die, sizeof die - 1);
		mce_exit_via_signal(sig);
		break;

	case SIGTSTP:
		/* Stopping mce could also lead to unrecoverable suspend */
		break;
#endif
	default:
		break;
	}

	/* transfer the signal to mainloop via pipe */
	int did = TEMP_FAILURE_RETRY(write(signal_pipe[1], &sig, sizeof sig));

	if( did != (int)sizeof sig ) {
		mce_abort();
	}
}
コード例 #22
0
ファイル: tst-cond12.c プロジェクト: AubrCool/glibc
static int
do_test (void)
{
  struct
  {
    pthread_mutex_t m;
    pthread_cond_t c;
    int var;
  } *p = mmap (NULL, sizeof (*p), PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
  if (p == MAP_FAILED)
    {
      printf ("initial mmap failed: %m\n");
      return 1;
    }

  pthread_mutexattr_t ma;
  if (pthread_mutexattr_init (&ma) != 0)
    {
      puts ("mutexattr_init failed");
      return 1;
    }
  if (pthread_mutexattr_setpshared (&ma, 1) != 0)
    {
      puts ("mutexattr_setpshared failed");
      return 1;
    }
  if (pthread_mutex_init (&p->m, &ma) != 0)
    {
      puts ("mutex_init failed");
      return 1;
    }
  if (pthread_mutexattr_destroy (&ma) != 0)
    {
      puts ("mutexattr_destroy failed");
      return 1;
    }

  pthread_condattr_t ca;
  if (pthread_condattr_init (&ca) != 0)
    {
      puts ("condattr_init failed");
      return 1;
    }
  if (pthread_condattr_setpshared (&ca, 1) != 0)
    {
      puts ("condattr_setpshared failed");
      return 1;
    }
  if (pthread_cond_init (&p->c, &ca) != 0)
    {
      puts ("mutex_init failed");
      return 1;
    }
  if (pthread_condattr_destroy (&ca) != 0)
    {
      puts ("condattr_destroy failed");
      return 1;
    }

  if (pthread_mutex_lock (&p->m) != 0)
    {
      puts ("initial mutex_lock failed");
      return 1;
    }

  p->var = 42;

  pid_t pid = fork ();
  if (pid == -1)
    {
      printf ("fork failed: %m\n");
      return 1;
    }

  if (pid == 0)
    {
      void *oldp = p;
      p = mmap (NULL, sizeof (*p), PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);

      if (p == oldp)
	{
	  puts ("child: mapped to same address");
	  kill (getppid (), SIGKILL);
	  exit (1);
	}

      munmap (oldp, sizeof (*p));

      if (pthread_mutex_lock (&p->m) != 0)
	{
	  puts ("child: mutex_lock failed");
	  kill (getppid (), SIGKILL);
	  exit (1);
	}

      p->var = 0;

#ifndef USE_COND_SIGNAL
      if (pthread_cond_broadcast (&p->c) != 0)
	{
	  puts ("child: cond_broadcast failed");
	  kill (getppid (), SIGKILL);
	  exit (1);
	}
#else
      if (pthread_cond_signal (&p->c) != 0)
	{
	  puts ("child: cond_signal failed");
	  kill (getppid (), SIGKILL);
	  exit (1);
	}
#endif

      if (pthread_mutex_unlock (&p->m) != 0)
	{
	  puts ("child: mutex_unlock failed");
	  kill (getppid (), SIGKILL);
	  exit (1);
	}

      exit (0);
    }

  do
    pthread_cond_wait (&p->c, &p->m);
  while (p->var != 0);

  if (TEMP_FAILURE_RETRY (waitpid (pid, NULL, 0)) != pid)
    {
      printf ("waitpid failed: %m\n");
      kill (pid, SIGKILL);
      return 1;
    }

  return 0;
}
コード例 #23
0
static void jdwp_process_event(int socket, unsigned events, void* _proc) {
    JdwpProcess* proc = reinterpret_cast<JdwpProcess*>(_proc);
    CHECK_EQ(socket, proc->socket);

    if (events & FDE_READ) {
        if (proc->pid < 0) {
            ssize_t rc = TEMP_FAILURE_RETRY(recv(socket, &proc->pid, sizeof(proc->pid), 0));
            if (rc != sizeof(proc->pid)) {
                D("failed to read jdwp pid: rc = %zd, errno = %s", rc, strerror(errno));
                goto CloseProcess;
            }

            /* all is well, keep reading to detect connection closure */
            D("Adding pid %d to jdwp process list", proc->pid);
            jdwp_process_list_updated();
        } else {
            // We already have the PID, if we can read from the socket, we've probably hit EOF.
            D("terminating JDWP connection %d", proc->pid);
            goto CloseProcess;
        }
    }

    if (events & FDE_WRITE) {
        D("trying to send fd to JDWP process (count = %zu)", proc->out_fds.size());
        CHECK(!proc->out_fds.empty());

        int fd = proc->out_fds.back().get();
        struct cmsghdr* cmsg;
        struct msghdr msg;
        struct iovec iov;
        char dummy = '!';
        char buffer[sizeof(struct cmsghdr) + sizeof(int)];

        iov.iov_base = &dummy;
        iov.iov_len = 1;
        msg.msg_name = nullptr;
        msg.msg_namelen = 0;
        msg.msg_iov = &iov;
        msg.msg_iovlen = 1;
        msg.msg_flags = 0;
        msg.msg_control = buffer;
        msg.msg_controllen = sizeof(buffer);

        cmsg = CMSG_FIRSTHDR(&msg);
        cmsg->cmsg_len = msg.msg_controllen;
        cmsg->cmsg_level = SOL_SOCKET;
        cmsg->cmsg_type = SCM_RIGHTS;
        ((int*)CMSG_DATA(cmsg))[0] = fd;

        int ret = TEMP_FAILURE_RETRY(sendmsg(socket, &msg, 0));
        if (ret < 0) {
            D("sending new file descriptor to JDWP %d failed: %s", proc->pid, strerror(errno));
            goto CloseProcess;
        }

        D("sent file descriptor %d to JDWP process %d", fd, proc->pid);

        proc->out_fds.pop_back();
        if (proc->out_fds.empty()) {
            fdevent_del(proc->fde, FDE_WRITE);
        }
    }

    return;

CloseProcess:
    proc->RemoveFromList();
    jdwp_process_list_updated();
}
コード例 #24
0
ファイル: task_cray.c プロジェクト: BYUHPC/slurm
/*
 * Check the status file for the exit of the given local task id
 * and terminate the job step if an improper exit is found
 */
static int _check_status_file(stepd_step_rec_t *job)
{
	char llifile[LLI_STATUS_FILE_BUF_SIZE];
	char status;
	int rv, fd;
	stepd_step_task_info_t *task;
	char *reason;

	// Get the lli file name
	snprintf(llifile, sizeof(llifile), LLI_STATUS_FILE,
		 SLURM_ID_HASH(job->jobid, job->stepid));

	// Open the lli file.
	fd = open(llifile, O_RDONLY);
	if (fd == -1) {
		CRAY_ERR("open(%s) failed: %m", llifile);
		return SLURM_ERROR;
	}

	// Read the first byte (indicates starting)
	rv = read(fd, &status, sizeof(status));
	if (rv == -1) {
		CRAY_ERR("read failed: %m");
		return SLURM_ERROR;
	}

	// If the first byte is 0, we either aren't an MPI app or
	// it didn't make it past pmi_init, in any case, return success
	if (status == 0) {
		TEMP_FAILURE_RETRY(close(fd));
		return SLURM_SUCCESS;
	}

	// Seek to the correct offset
	rv = lseek(fd, job->envtp->localid + 1, SEEK_SET);
	if (rv == -1) {
		CRAY_ERR("lseek failed: %m");
		TEMP_FAILURE_RETRY(close(fd));
		return SLURM_ERROR;
	}

	// Read the exiting byte
	rv = read(fd, &status, sizeof(status));
	TEMP_FAILURE_RETRY(close(fd));
	if (rv == -1) {
		CRAY_ERR("read failed: %m");
		return SLURM_SUCCESS;
	}

	// Check the result
	if (status == 0 && !terminated) {
		task = job->task[job->envtp->localid];
		if (task->killed_by_cmd) {
			// We've been killed by request. User already knows
			return SLURM_SUCCESS;
		} else if (task->aborted) {
			reason = "aborted";
		} else if (WIFSIGNALED(task->estatus)) {
			reason = "signaled";
		} else {
			reason = "exited";
		}

		// Cancel the job step, since we didn't find the exiting msg
		error("Terminating job step %"PRIu32".%"PRIu32
			"; task %d exit code %d %s without notification",
			job->jobid, job->stepid, task->gtid,
			WEXITSTATUS(task->estatus), reason);
		terminated = 1;
		slurm_terminate_job_step(job->jobid, job->stepid);
	}
	return SLURM_SUCCESS;
}
コード例 #25
0
ファイル: logd_write.c プロジェクト: 0omega/platform_bionic
/* Important: see technical note at start of source file */
static int __write_to_log_kernel(log_id_t log_id, struct iovec *vec)
{
    return TEMP_FAILURE_RETRY( writev(log_channels[log_id].fd, vec, 3) );
}
コード例 #26
0
ファイル: csjp_logger.cpp プロジェクト: csjpeter/libcsjp
/*
 * Author: Csaszar, Peter <*****@*****.**>
 * Copyright (C) 2009-2012 Csaszar, Peter
 */

#include <sys/time.h>
#include <sys/stat.h>

#include <unistd.h>

#include <errno.h>
#include <time.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>

#ifdef FCLOG
#include <fclog.h>
#endif

#include "csjp_logger.h"

namespace csjp {

static void dateStamp(char res[16])
{
	time_t t = time(NULL);
	strftime(res, 16, "%Y-%m-%d-%a", localtime(&t));
}

static void timeStamp(char res[16])
{
	char timeStr[16] = {0};
	timeval unixTime;

	gettimeofday(&unixTime, NULL);
	time_t t = unixTime.tv_sec;
	int unixMillisecs = unixTime.tv_usec/1000;
	struct tm _tm;

	localtime_r(&t, &_tm);
	strftime(timeStr, sizeof(timeStr), "%H:%M:%S", &_tm);
	snprintf(res, 16, "%s:%03d", timeStr, unixMillisecs);
}

static char g_LogDir[256] = {0};
static char g_LogFileName[512] = {0};
static char g_LogFileNameSpecializer[128] = {0};
static char g_BinaryName[128] = "unknown";
bool verboseMode = false;
bool haveLogDir = true;

void resetLogFileName()
{
	g_LogFileName[0] = 0;
}

void setLogDir(const char * dir)
{
	if(dir)
		strncpy(g_LogDir, dir, sizeof(g_LogDir));
	else
		strncpy(g_LogDir, "./", sizeof(g_LogDir));
	haveLogDir = true;
	resetLogFileName();
}

void setBinaryName(const char * name)
{
	if(!name)
		return;

	const char *baseName = strrchr(name, '/');
	baseName = baseName ? baseName + 1 : name;
	strncpy(g_BinaryName, baseName, sizeof(g_BinaryName));

	resetLogFileName();
}

const char * getBinaryName()
{
	return g_BinaryName;
}

const char * logFileName()
{
#ifdef FCLOG
	return FCLOG_FILE;
#else
	if(g_LogFileName[0] == 0 && haveLogDir){
		struct stat fileStat;
		if(0 <= stat(g_LogDir, &fileStat))
			if(S_ISDIR(fileStat.st_mode)){
				snprintf(g_LogFileName, sizeof(g_LogFileName),
						"%s/%s%s.log", g_LogDir,
						g_BinaryName, g_LogFileNameSpecializer);
				return g_LogFileName;
			}
		haveLogDir = false;
	}
	return g_LogFileName;
#endif
}

void setLogFileNameSpecializer(const char * str)
{
	if(str != NULL){
		g_LogFileNameSpecializer[0] = '.';
		strncpy(g_LogFileNameSpecializer + 1, str, sizeof(g_LogFileNameSpecializer) - 1);
	} else
		g_LogFileNameSpecializer[0] = 0;
	resetLogFileName();
}

static unsigned loggerMutex = 0; /* Initialized before main() */
void msgLogger(FILE * stdfile, const char * string, size_t length)
{
	if(!length)
		length = strlen(string);

	char header[64];
	{
		char time_stamp[16];
		timeStamp(time_stamp);

		char date_stamp[16];
		dateStamp(date_stamp);

		double c = (double)(clock())/(double)(CLOCKS_PER_SEC);

		snprintf(header, sizeof(header), "%14s %12s %7.3f %5d",
				date_stamp, time_stamp, c, getpid());
	}

	const char * fmt = "%s %s ";

#if ! _ISOC99_SOURCE
#error We need to use C99 for calculating printed number of characters with vsnprintf().
#endif

	/* Now lets calculate the amount of memory needed by the full log message. */
	int size = 0;
	size += strlen(fmt);
	size += sizeof(header);
	size += length;

	/* Allocate memory */
	char * msg = (char*)malloc(size);
	if(!msg){
		if(stderr)
			fprintf(stderr, VT_RED VT_TA_BOLD "ERROR" VT_NORMAL
					"No enoguh memory for log message!");
		return;
	}

	/* Compose the log message */
	int len = snprintf(msg, size, fmt, header, string);
	if(len < 0){
		if(stderr)
			fprintf(stderr, VT_RED VT_TA_BOLD "ERROR" VT_NORMAL
					"Failed to snprintf the log message and its header!\n");
		free(msg);
		return;
	}

	msg[len++] = '\n';
	msg[len] = 0;

	/* We need to have logging thread safe.
	 * We should not use posix mutex since that might fail, and
	 * on posix failure we should report the issue, thus call
	 * this logger. This would be a circular dependency and a
	 * possible place to have infinite recursion.
	 *
	 * So we are going to use gcc special low level atomic operations.
	 * http://gcc.gnu.org/onlinedocs/gcc-4.1.2/gcc/Atomic-Builtins.html#Atomic-Builtins
	 * type __sync_fetch_and_add (type *ptr, type value, ...)
	 * type __sync_fetch_and_sub (type *ptr, type value, ...)
	 */
#if not __GNUC__ >= 4
#error "We need gcc 4 or later for __sync_fetch_and_add() and __sync_fetch_and_sub()"
#endif
	unsigned loggerMutexLast = 1;
	while(loggerMutexLast){
		loggerMutexLast = __sync_fetch_and_add(&loggerMutex, 1);
		if(loggerMutexLast){
			__sync_fetch_and_sub(&loggerMutex, 1);
			usleep(100);
		}
	}

	if(haveLogDir && logFileName()[0]){
		FILE *log = fopen(logFileName(), "a");
		if(log){
			fputs(msg, log);
			fflush(log);
			TEMP_FAILURE_RETRY( fclose(log) );
		} else if(stderr) {
			fprintf(stderr, VT_RED VT_TA_BOLD "ERROR" VT_NORMAL
					" Could not open logfile: %s\n", logFileName());
			haveLogDir = false;
		}
	}

	basicLogger(msg, stdfile, g_BinaryName);

	__sync_fetch_and_sub(&loggerMutex, 1);

	free(msg);
}
コード例 #27
0
/**
 * \brief 绑定监听服务到某一个端口
 * \param name 绑定端口名称
 * \param port 具体绑定的端口
 * \return 绑定是否成功
 */
bool zTCPServer::bind(const std::string &name, const unsigned short port)
{
	Zebra::logger->trace("zTCPServer::bind");
	struct sockaddr_in addr;

	if (-1 != sock) 
	{
		Zebra::logger->error("服务器可能已经初始化");;
		return false;
	}

	sock = ::socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
	if (-1 == sock) 
	{
		Zebra::logger->error("创建套接口失败");
		return false;
	}

	//设置套接口为可重用状态
	int reuse = 1;
	if (-1 == ::setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse))) 
	{
		Zebra::logger->error("不能设置套接口为可重用状态");
		TEMP_FAILURE_RETRY(::close(sock));
		sock = -1;
		return false;
	}

	//设置套接口发送接收缓冲,并且服务器的必须在accept之前设置
	socklen_t window_size = 128 * 1024;
	if (-1 == ::setsockopt(sock, SOL_SOCKET, SO_RCVBUF, &window_size, sizeof(window_size)))
	{
		TEMP_FAILURE_RETRY(::close(sock));
		return false;
	}
	if (-1 == ::setsockopt(sock, SOL_SOCKET, SO_SNDBUF, &window_size, sizeof(window_size)))
	{
		TEMP_FAILURE_RETRY(::close(sock));
		return false;
	}

	bzero(&addr, sizeof(addr));
	addr.sin_family = AF_INET;
	addr.sin_addr.s_addr = htonl(INADDR_ANY);
	addr.sin_port = htons(port);

	int retcode = ::bind(sock, (struct sockaddr *) &addr, sizeof(addr));
	if (-1 == retcode) 
	{
		Zebra::logger->error("不能绑定服务器端口");
		TEMP_FAILURE_RETRY(::close(sock));
		sock = -1;
		return false;
	}

	retcode = ::listen(sock, MAX_WAITQUEUE);
	if (-1 == retcode) 
	{
		Zebra::logger->error("监听套接口失败");
		TEMP_FAILURE_RETRY(::close(sock));
		sock = -1;
		return false;
	}

#ifdef _USE_EPOLL_
	struct epoll_event ev;
	ev.events = EPOLLIN;
	ev.data.ptr = NULL;
	assert(0 == epoll_ctl(kdpfd, EPOLL_CTL_ADD, sock, &ev));
#endif

	Zebra::logger->info("初始化 %s:%u 成功", name.c_str(), port);

	return true;
}
コード例 #28
0
static void unmount_and_fsck(const struct mntent *entry)
{
#ifndef UMOUNT_AND_FSCK_IS_UNSAFE
    if (strcmp(entry->mnt_type, "f2fs") && strcmp(entry->mnt_type, "ext4"))
        return;

    /* First, lazily unmount the directory. This unmount request finishes when
     * all processes that open a file or directory in |entry->mnt_dir| exit.
     */
    TEMP_FAILURE_RETRY(umount2(entry->mnt_dir, MNT_DETACH));

    /* Next, kill all processes except init, kthreadd, and kthreadd's
     * children to finish the lazy unmount. Killing all processes here is okay
     * because this callback function is only called right before reboot().
     * It might be cleaner to selectively kill processes that actually use
     * |entry->mnt_dir| rather than killing all, probably by reusing a function
     * like killProcessesWithOpenFiles() in vold/, but the selinux policy does
     * not allow init to scan /proc/<pid> files which the utility function
     * heavily relies on. The policy does not allow the process to execute
     * killall/pkill binaries either. Note that some processes might
     * automatically restart after kill(), but that is not really a problem
     * because |entry->mnt_dir| is no longer visible to such new processes.
     */
    service_for_each(service_stop);
    TEMP_FAILURE_RETRY(kill(-1, SIGKILL));

    int count = 0;
    while (count++ < UNMOUNT_CHECK_TIMES) {
        int fd = TEMP_FAILURE_RETRY(open(entry->mnt_fsname, O_RDONLY | O_EXCL));
        if (fd >= 0) {
            /* |entry->mnt_dir| has sucessfully been unmounted. */
            close(fd);
            break;
        } else if (errno == EBUSY) {
            /* Some processes using |entry->mnt_dir| are still alive. Wait for a
             * while then retry.
             */
            TEMP_FAILURE_RETRY(
                usleep(UNMOUNT_CHECK_MS * 1000 / UNMOUNT_CHECK_TIMES));
            continue;
        } else {
            /* Cannot open the device. Give up. */
            return;
        }
    }

    int st;
    if (!strcmp(entry->mnt_type, "f2fs")) {
        const char *f2fs_argv[] = {
            "/system/bin/fsck.f2fs", "-f", entry->mnt_fsname,
        };
        android_fork_execvp_ext(ARRAY_SIZE(f2fs_argv), (char **)f2fs_argv,
                                &st, true, LOG_KLOG, true, NULL);
    } else if (!strcmp(entry->mnt_type, "ext4")) {
        const char *ext4_argv[] = {
            "/system/bin/e2fsck", "-f", "-y", entry->mnt_fsname,
        };
        android_fork_execvp_ext(ARRAY_SIZE(ext4_argv), (char **)ext4_argv,
                                &st, true, LOG_KLOG, true, NULL);
    }
#endif
}
コード例 #29
0
/*
 * This function might request a reboot, in which case it will
 * not return.
 */
int do_mount_all(int nargs, char **args)
{
    pid_t pid;
    int ret = -1;
    int child_ret = -1;
    int status;
    char boot_mode[PROP_VALUE_MAX] = {0};
    struct fstab *fstab;

    if (nargs != 2) {
        return -1;
    }

    /*
     * Call fs_mgr_mount_all() to mount all filesystems.  We fork(2) and
     * do the call in the child to provide protection to the main init
     * process if anything goes wrong (crash or memory leak), and wait for
     * the child to finish in the parent.
     */
    pid = fork();
    if (pid > 0) {
        /* Parent.  Wait for the child to return */
        int wp_ret = TEMP_FAILURE_RETRY(waitpid(pid, &status, 0));
        if (wp_ret < 0) {
            /* Unexpected error code. We will continue anyway. */
            NOTICE("waitpid failed rc=%d: %s\n", wp_ret, strerror(errno));
        }

        if (WIFEXITED(status)) {
            ret = WEXITSTATUS(status);
        } else {
            ret = -1;
        }
    } else if (pid == 0) {
        /* child, call fs_mgr_mount_all() */
        klog_set_level(6);  /* So we can see what fs_mgr_mount_all() does */
        fstab = fs_mgr_read_fstab(args[1]);
        child_ret = fs_mgr_mount_all(fstab);
        fs_mgr_free_fstab(fstab);
        if (child_ret == -1) {
            ERROR("fs_mgr_mount_all returned an error\n");
        }
        _exit(child_ret);
    } else {
        /* fork failed, return an error */
        return -1;
    }

    if (ret == FS_MGR_MNTALL_DEV_NEEDS_ENCRYPTION) {
        property_set("vold.decrypt", "trigger_encryption");
    } else if (ret == FS_MGR_MNTALL_DEV_MIGHT_BE_ENCRYPTED) {
        property_set("ro.crypto.state", "encrypted");
        property_set("ro.crypto.type", "block");
        property_set("vold.decrypt", "trigger_default_encryption");
    } else if (ret == FS_MGR_MNTALL_DEV_NOT_ENCRYPTED) {
        property_set("ro.crypto.state", "unencrypted");
        /* If fs_mgr determined this is an unencrypted device and we are
         * not booting into ffbm(fast factory boot mode),then trigger
	 * that action.
         */
        property_get("ro.bootmode", boot_mode);
        if (strncmp(boot_mode, "ffbm", 4))
            action_for_each_trigger("nonencrypted", action_add_queue_tail);
    } else if (ret == FS_MGR_MNTALL_DEV_NEEDS_RECOVERY) {
        /* Setup a wipe via recovery, and reboot into recovery */
        ERROR("fs_mgr_mount_all suggested recovery, so wiping data via recovery.\n");
        ret = wipe_data_via_recovery();
        /* If reboot worked, there is no return. */
    } else if (ret == FS_MGR_MNTALL_DEV_DEFAULT_FILE_ENCRYPTED) {
        if (e4crypt_install_keyring()) {
            return -1;
        }
        property_set("ro.crypto.state", "encrypted");
        property_set("ro.crypto.type", "file");

        // Although encrypted, we have device key, so we do not need to
        // do anything different from the nonencrypted case.
        property_get("ro.bootmode", boot_mode);
        if (strncmp(boot_mode, "ffbm", 4))
            action_for_each_trigger("nonencrypted", action_add_queue_tail);
    } else if (ret == FS_MGR_MNTALL_DEV_NON_DEFAULT_FILE_ENCRYPTED) {
        if (e4crypt_install_keyring()) {
            return -1;
        }
        property_set("ro.crypto.state", "encrypted");
        property_set("ro.crypto.type", "file");
        property_set("vold.decrypt", "trigger_restart_min_framework");
    } else if (ret > 0) {
        ERROR("fs_mgr_mount_all returned unexpected error %d\n", ret);
    }
    /* else ... < 0: error */

    return ret;
}
コード例 #30
-1
ファイル: task_cray.c プロジェクト: alejluther/slurm
/*
 * task_term() is called after termination of application task.
 *	It is preceded by --task-epilog (from srun command line)
 *	followed by TaskEpilog program (from slurm.conf).
 */
extern int task_p_post_term (stepd_step_rec_t *job,
			     stepd_step_task_info_t *task)
{
#ifdef HAVE_NATIVE_CRAY
	char llifile[LLI_STATUS_FILE_BUF_SIZE];
	char status;
	int rv, fd;

	debug("task_p_post_term: %u.%u, task %d",
	      job->jobid, job->stepid, job->envtp->procid);

	// Get the lli file name
	snprintf(llifile, sizeof(llifile), LLI_STATUS_FILE,
		 SLURM_ID_HASH(job->jobid, job->stepid));

	// Open the lli file.
	fd = open(llifile, O_RDONLY);
	if (fd == -1) {
		error("%s: open(%s) failed: %m", __func__, llifile);
		return SLURM_ERROR;
	}

	// Read the first byte (indicates starting)
	rv = read(fd, &status, sizeof(status));
	if (rv == -1) {
		error("%s: read failed: %m", __func__);
		return SLURM_ERROR;
	}

	// If the first byte is 0, we either aren't an MPI app or
	// it didn't make it past pmi_init, in any case, return success
	if (status == 0) {
		TEMP_FAILURE_RETRY(close(fd));
		return SLURM_SUCCESS;
	}

	// Seek to the correct offset (job->envtp->localid + 1)
	rv = lseek(fd, job->envtp->localid + 1, SEEK_SET);
	if (rv == -1) {
		error("%s: lseek failed: %m", __func__);
		TEMP_FAILURE_RETRY(close(fd));
		return SLURM_ERROR;
	}

	// Read the exiting byte
	rv = read(fd, &status, sizeof(status));
	TEMP_FAILURE_RETRY(close(fd));
	if (rv == -1) {
		error("%s: read failed: %m", __func__);
		return SLURM_SUCCESS;
	}

	// Check the result
	if (status == 0) {
		// Cancel the job step, since we didn't find the exiting msg
		fprintf(stderr, "Terminating job step, task %d improper exit\n",
			job->envtp->procid);
		slurm_terminate_job_step(job->jobid, job->stepid);
	}

#endif
	return SLURM_SUCCESS;
}