hjl / source-git / glibc

Forked from source-git/glibc 4 years ago
Clone

Blame sysdeps/unix/sysv/linux/tst-setgetname.c

Packit 6c4009
/* Test pthread_setname_np and pthread_getname_np.
Packit 6c4009
   Copyright (C) 2013-2018 Free Software Foundation, Inc.
Packit 6c4009
   This file is part of the GNU C Library.
Packit 6c4009
Packit 6c4009
   The GNU C Library is free software; you can redistribute it and/or
Packit 6c4009
   modify it under the terms of the GNU Lesser General Public License as
Packit 6c4009
   published by the Free Software Foundation; either version 2.1 of the
Packit 6c4009
   License, or (at your option) any later version.
Packit 6c4009
Packit 6c4009
   The GNU C Library is distributed in the hope that it will be useful,
Packit 6c4009
   but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit 6c4009
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit 6c4009
   Lesser General Public License for more details.
Packit 6c4009
Packit 6c4009
   You should have received a copy of the GNU Lesser General Public
Packit 6c4009
   License along with the GNU C Library; see the file COPYING.LIB.  If
Packit 6c4009
   not, see <http://www.gnu.org/licenses/>.  */
Packit 6c4009
#include <stdio.h>
Packit 6c4009
#include <stdlib.h>
Packit 6c4009
#include <pthread.h>
Packit 6c4009
#include <string.h>
Packit 6c4009
#include <sys/syscall.h>
Packit 6c4009
#include <unistd.h>
Packit 6c4009
#include <fcntl.h>
Packit 6c4009
#include <errno.h>
Packit 6c4009
Packit 6c4009
/* New name of process.  */
Packit 6c4009
#define NEW_NAME "setname"
Packit 6c4009
Packit 6c4009
/* Name of process which is one byte too big
Packit 6c4009
   e.g. 17 bytes including null-terminator  */
Packit 6c4009
#define BIG_NAME       "....V....X....XV"
Packit 6c4009
Packit 6c4009
/* Longest name of a process
Packit 6c4009
   e.g. 16 bytes including null-terminator.  */
Packit 6c4009
#define LONGEST_NAME   "....V....X....X"
Packit 6c4009
Packit 6c4009
/* One less than longest name with unique
Packit 6c4009
   characters to detect modification.  */
Packit 6c4009
#define CANARY_NAME    "abcdefghijklmn"
Packit 6c4009
Packit 6c4009
/* On Linux the maximum length of the name of a task *including* the null
Packit 6c4009
   terminator.  */
Packit 6c4009
#define TASK_COMM_LEN 16
Packit 6c4009
Packit 6c4009
long
Packit 6c4009
gettid (void)
Packit 6c4009
{
Packit 6c4009
    return syscall(__NR_gettid);
Packit 6c4009
}
Packit 6c4009
Packit 6c4009
/* On Linux we can read this task's name from /proc.  */
Packit 6c4009
int
Packit 6c4009
get_self_comm (long tid, char *buf, size_t len)
Packit 6c4009
{
Packit 6c4009
  int res = 0;
Packit 6c4009
#define FMT "/proc/self/task/%lu/comm"
Packit 6c4009
  char fname[sizeof (FMT) + 32];
Packit 6c4009
  sprintf (fname, FMT, (unsigned long) tid);
Packit 6c4009
Packit 6c4009
  int fd = open (fname, O_RDONLY);
Packit 6c4009
  if (fd == -1)
Packit 6c4009
    return errno;
Packit 6c4009
Packit 6c4009
  ssize_t n = read (fd, (void *) buf, len);
Packit 6c4009
  if (n < 0)
Packit 6c4009
    res = errno;
Packit 6c4009
  else
Packit 6c4009
    {
Packit 6c4009
      if (buf[n - 1] == '\n')
Packit 6c4009
        buf[n - 1] = '\0';
Packit 6c4009
      else if (n == len)
Packit 6c4009
        res = ERANGE;
Packit 6c4009
      else
Packit 6c4009
        buf[n] = '\0';
Packit 6c4009
    }
Packit 6c4009
Packit 6c4009
  close (fd);
Packit 6c4009
  return res;
Packit 6c4009
}
Packit 6c4009
Packit 6c4009
int
Packit 6c4009
do_test (int argc, char **argv)
Packit 6c4009
{
Packit 6c4009
  pthread_t self;
Packit 6c4009
  int res;
Packit 6c4009
  int ret = 0;
Packit 6c4009
  char name[TASK_COMM_LEN];
Packit 6c4009
  char name_check[TASK_COMM_LEN];
Packit 6c4009
Packit 6c4009
  memset (name, '\0', TASK_COMM_LEN);
Packit 6c4009
  memset (name_check, '\0', TASK_COMM_LEN);
Packit 6c4009
Packit 6c4009
  /* Test 1: Get the name of the task via pthread_getname_np and /proc
Packit 6c4009
     and verify that they both match.  */
Packit 6c4009
  self = pthread_self ();
Packit 6c4009
  res = pthread_getname_np (self, name, TASK_COMM_LEN);
Packit 6c4009
Packit 6c4009
  if (res == 0)
Packit 6c4009
    {
Packit 6c4009
      res = get_self_comm (gettid (), name_check, TASK_COMM_LEN);
Packit 6c4009
Packit 6c4009
      if (res == 0)
Packit 6c4009
       {
Packit 6c4009
         if (strncmp (name, name_check, strlen (BIG_NAME)) == 0)
Packit 6c4009
           printf ("PASS: Test 1 - pthread_getname_np and /proc agree.\n");
Packit 6c4009
         else
Packit 6c4009
           {
Packit 6c4009
             printf ("FAIL: Test 1 - pthread_getname_np and /proc differ"
Packit 6c4009
                     " i.e. %s != %s\n", name, name_check);
Packit 6c4009
             ret++;
Packit 6c4009
           }
Packit 6c4009
       }
Packit 6c4009
      else
Packit 6c4009
       {
Packit 6c4009
         printf ("FAIL: Test 1 - unable read task name via proc.\n");
Packit 6c4009
         ret++;
Packit 6c4009
        }
Packit 6c4009
    }
Packit 6c4009
  else
Packit 6c4009
    {
Packit 6c4009
      printf ("FAIL: Test 1 - pthread_getname_np failed with error %d\n", res);
Packit 6c4009
      ret++;
Packit 6c4009
    }
Packit 6c4009
Packit 6c4009
  /* Test 2: Test setting the name and then independently verify it
Packit 6c4009
             was set.  */
Packit 6c4009
  res = pthread_setname_np (self, NEW_NAME);
Packit 6c4009
Packit 6c4009
  if (res == 0)
Packit 6c4009
    {
Packit 6c4009
      res = get_self_comm (gettid (), name_check, TASK_COMM_LEN);
Packit 6c4009
      if (res == 0)
Packit 6c4009
        {
Packit 6c4009
         if (strncmp (NEW_NAME, name_check, strlen (BIG_NAME)) == 0)
Packit 6c4009
           printf ("PASS: Test 2 - Value used in pthread_setname_np and"
Packit 6c4009
                   " /proc agree.\n");
Packit 6c4009
         else
Packit 6c4009
           {
Packit 6c4009
             printf ("FAIL: Test 2 - Value used in pthread_setname_np"
Packit 6c4009
		     " and /proc differ i.e. %s != %s\n",
Packit 6c4009
		     NEW_NAME, name_check);
Packit 6c4009
             ret++;
Packit 6c4009
           }
Packit 6c4009
        }
Packit 6c4009
      else
Packit 6c4009
       {
Packit 6c4009
         printf ("FAIL: Test 2 - unable to read task name via proc.\n");
Packit 6c4009
         ret++;
Packit 6c4009
        }
Packit 6c4009
    }
Packit 6c4009
  else
Packit 6c4009
    {
Packit 6c4009
      printf ("FAIL: Test 2 - pthread_setname_np failed with error %d\n", res);
Packit 6c4009
      ret++;
Packit 6c4009
    }
Packit 6c4009
Packit 6c4009
  /* Test 3: Test setting a name that is one-byte too big.  */
Packit 6c4009
  res = pthread_getname_np (self, name, TASK_COMM_LEN);
Packit 6c4009
Packit 6c4009
  if (res == 0)
Packit 6c4009
    {
Packit 6c4009
      res = pthread_setname_np (self, BIG_NAME);
Packit 6c4009
      if (res != 0)
Packit 6c4009
        {
Packit 6c4009
         if (res == ERANGE)
Packit 6c4009
           {
Packit 6c4009
             printf ("PASS: Test 3 - pthread_setname_np returned ERANGE"
Packit 6c4009
                     " for a process name that was too long.\n");
Packit 6c4009
Packit 6c4009
             /* Verify the old name didn't change.  */
Packit 6c4009
             res = get_self_comm (gettid (), name_check, TASK_COMM_LEN);
Packit 6c4009
             if (res == 0)
Packit 6c4009
               {
Packit 6c4009
                 if (strncmp (name, name_check, strlen (BIG_NAME)) == 0)
Packit 6c4009
                   printf ("PASS: Test 3 - Original name unchanged after"
Packit 6c4009
                           " pthread_setname_np returned ERANGE.\n");
Packit 6c4009
                 else
Packit 6c4009
                   {
Packit 6c4009
                     printf ("FAIL: Test 3 - Original name changed after"
Packit 6c4009
                             " pthread_setname_np returned ERANGE"
Packit 6c4009
                             " i.e. %s != %s\n",
Packit 6c4009
                             name, name_check);
Packit 6c4009
                     ret++;
Packit 6c4009
                   }
Packit 6c4009
               }
Packit 6c4009
             else
Packit 6c4009
               {
Packit 6c4009
                 printf ("FAIL: Test 3 - unable to read task name.\n");
Packit 6c4009
                 ret++;
Packit 6c4009
               }
Packit 6c4009
           }
Packit 6c4009
         else
Packit 6c4009
           {
Packit 6c4009
             printf ("FAIL: Test 3 - Wrong error returned"
Packit 6c4009
		     " i.e. ERANGE != %d\n", res);
Packit 6c4009
             ret++;
Packit 6c4009
           }
Packit 6c4009
        }
Packit 6c4009
      else
Packit 6c4009
        {
Packit 6c4009
         printf ("FAIL: Test 3 - Too-long name accepted by"
Packit 6c4009
	         " pthread_setname_np.\n");
Packit 6c4009
         ret++;
Packit 6c4009
        }
Packit 6c4009
    }
Packit 6c4009
  else
Packit 6c4009
    {
Packit 6c4009
      printf ("FAIL: Test 3 - Unable to get original name.\n");
Packit 6c4009
      ret++;
Packit 6c4009
    }
Packit 6c4009
Packit 6c4009
  /* Test 4: Verify that setting the longest name works.  */
Packit 6c4009
  res = pthread_setname_np (self, LONGEST_NAME);
Packit 6c4009
Packit 6c4009
  if (res == 0)
Packit 6c4009
    {
Packit 6c4009
      res = get_self_comm (gettid (), name_check, TASK_COMM_LEN);
Packit 6c4009
      if (res == 0)
Packit 6c4009
        {
Packit 6c4009
         if (strncmp (LONGEST_NAME, name_check, strlen (BIG_NAME)) == 0)
Packit 6c4009
           printf ("PASS: Test 4 - Longest name set via pthread_setname_np"
Packit 6c4009
                   " agrees with /proc.\n");
Packit 6c4009
         else
Packit 6c4009
           {
Packit 6c4009
             printf ("FAIL: Test 4 - Value used in pthread_setname_np and /proc"
Packit 6c4009
		     " differ i.e. %s != %s\n", LONGEST_NAME, name_check);
Packit 6c4009
             ret++;
Packit 6c4009
           }
Packit 6c4009
        }
Packit 6c4009
      else
Packit 6c4009
       {
Packit 6c4009
         printf ("FAIL: Test 4 - unable to read task name via proc.\n");
Packit 6c4009
         ret++;
Packit 6c4009
        }
Packit 6c4009
    }
Packit 6c4009
  else
Packit 6c4009
    {
Packit 6c4009
      printf ("FAIL: Test 4 - pthread_setname_np failed with error %d\n", res);
Packit 6c4009
      ret++;
Packit 6c4009
    }
Packit 6c4009
Packit 6c4009
  /* Test 5: Verify that getting a long name into a small buffer fails.  */
Packit 6c4009
  strncpy (name, CANARY_NAME, strlen (CANARY_NAME) + 1);
Packit 6c4009
Packit 6c4009
  /* Claim the buffer length is strlen (LONGEST_NAME).  This is one character
Packit 6c4009
     too small to hold LONGEST_NAME *and* the null terminator.  We should get
Packit 6c4009
     back ERANGE and name should be unmodified.  */
Packit 6c4009
  res = pthread_getname_np (self, name, strlen (LONGEST_NAME));
Packit 6c4009
Packit 6c4009
  if (res != 0)
Packit 6c4009
    {
Packit 6c4009
      if (res == ERANGE)
Packit 6c4009
        {
Packit 6c4009
	  if (strncmp (CANARY_NAME, name, strlen (BIG_NAME)) == 0)
Packit 6c4009
	    {
Packit 6c4009
	      printf ("PASS: Test 5 - ERANGE and buffer unmodified.\n");
Packit 6c4009
	    }
Packit 6c4009
	  else
Packit 6c4009
	    {
Packit 6c4009
	      printf ("FAIL: Test 5 - Original buffer modified.\n");
Packit 6c4009
	      ret++;
Packit 6c4009
	    }
Packit 6c4009
        }
Packit 6c4009
      else
Packit 6c4009
        {
Packit 6c4009
	  printf ("FAIL: Test 5 - Did not return ERANGE for small buffer.\n");
Packit 6c4009
	  ret++;
Packit 6c4009
        }
Packit 6c4009
    }
Packit 6c4009
  else
Packit 6c4009
    {
Packit 6c4009
      printf ("FAIL: Test 5 - Returned name longer than buffer.\n");
Packit 6c4009
      ret++;
Packit 6c4009
    }
Packit 6c4009
Packit 6c4009
  /* Test 6: Lastly make sure we can read back the longest name.  */
Packit 6c4009
  res = pthread_getname_np (self, name, strlen (LONGEST_NAME) + 1);
Packit 6c4009
Packit 6c4009
  if (res == 0)
Packit 6c4009
    {
Packit 6c4009
      if (strncmp (LONGEST_NAME, name, strlen (BIG_NAME)) == 0)
Packit 6c4009
        {
Packit 6c4009
	  printf ("PASS: Test 6 - Read back longest name correctly.\n");
Packit 6c4009
        }
Packit 6c4009
      else
Packit 6c4009
        {
Packit 6c4009
	  printf ("FAIL: Test 6 - Read \"%s\" instead of longest name.\n",
Packit 6c4009
		  name);
Packit 6c4009
	  ret++;
Packit 6c4009
        }
Packit 6c4009
    }
Packit 6c4009
  else
Packit 6c4009
    {
Packit 6c4009
      printf ("FAIL: Test 6 - pthread_getname_np failed with error %d\n", res);
Packit 6c4009
      ret++;
Packit 6c4009
    }
Packit 6c4009
Packit 6c4009
  return ret;
Packit 6c4009
}
Packit 6c4009
Packit 6c4009
#include <test-skeleton.c>