mirror of
https://sourceware.org/git/glibc.git
synced 2024-12-16 16:10:06 +00:00
5a82c74822
Also, change sources.redhat.com to sourceware.org. This patch was automatically generated by running the following shell script, which uses GNU sed, and which avoids modifying files imported from upstream: sed -ri ' s,(http|ftp)(://(.*\.)?(gnu|fsf|sourceware)\.org($|[^.]|\.[^a-z])),https\2,g s,(http|ftp)(://(.*\.)?)sources\.redhat\.com($|[^.]|\.[^a-z]),https\2sourceware.org\4,g ' \ $(find $(git ls-files) -prune -type f \ ! -name '*.po' \ ! -name 'ChangeLog*' \ ! -path COPYING ! -path COPYING.LIB \ ! -path manual/fdl-1.3.texi ! -path manual/lgpl-2.1.texi \ ! -path manual/texinfo.tex ! -path scripts/config.guess \ ! -path scripts/config.sub ! -path scripts/install-sh \ ! -path scripts/mkinstalldirs ! -path scripts/move-if-change \ ! -path INSTALL ! -path locale/programs/charmap-kw.h \ ! -path po/libc.pot ! -path sysdeps/gnu/errlist.c \ ! '(' -name configure \ -execdir test -f configure.ac -o -f configure.in ';' ')' \ ! '(' -name preconfigure \ -execdir test -f preconfigure.ac ';' ')' \ -print) and then by running 'make dist-prepare' to regenerate files built from the altered files, and then executing the following to cleanup: chmod a+x sysdeps/unix/sysv/linux/riscv/configure # Omit irrelevant whitespace and comment-only changes, # perhaps from a slightly-different Autoconf version. git checkout -f \ sysdeps/csky/configure \ sysdeps/hppa/configure \ sysdeps/riscv/configure \ sysdeps/unix/sysv/linux/csky/configure # Omit changes that caused a pre-commit check to fail like this: # remote: *** error: sysdeps/powerpc/powerpc64/ppc-mcount.S: trailing lines git checkout -f \ sysdeps/powerpc/powerpc64/ppc-mcount.S \ sysdeps/unix/sysv/linux/s390/s390-64/syscall.S # Omit change that caused a pre-commit check to fail like this: # remote: *** error: sysdeps/sparc/sparc64/multiarch/memcpy-ultra3.S: last line does not end in newline git checkout -f sysdeps/sparc/sparc64/multiarch/memcpy-ultra3.S
297 lines
8.1 KiB
C
297 lines
8.1 KiB
C
/* Test pthread_setname_np and pthread_getname_np.
|
|
Copyright (C) 2013-2019 Free Software Foundation, Inc.
|
|
This file is part of the GNU C Library.
|
|
|
|
The GNU C Library is free software; you can redistribute it and/or
|
|
modify it under the terms of the GNU Lesser General Public License as
|
|
published by the Free Software Foundation; either version 2.1 of the
|
|
License, or (at your option) any later version.
|
|
|
|
The GNU C Library is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
Lesser General Public License for more details.
|
|
|
|
You should have received a copy of the GNU Lesser General Public
|
|
License along with the GNU C Library; see the file COPYING.LIB. If
|
|
not, see <https://www.gnu.org/licenses/>. */
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <pthread.h>
|
|
#include <string.h>
|
|
#include <sys/syscall.h>
|
|
#include <unistd.h>
|
|
#include <fcntl.h>
|
|
#include <errno.h>
|
|
|
|
/* New name of process. */
|
|
#define NEW_NAME "setname"
|
|
|
|
/* Name of process which is one byte too big
|
|
e.g. 17 bytes including null-terminator */
|
|
#define BIG_NAME "....V....X....XV"
|
|
|
|
/* Longest name of a process
|
|
e.g. 16 bytes including null-terminator. */
|
|
#define LONGEST_NAME "....V....X....X"
|
|
|
|
/* One less than longest name with unique
|
|
characters to detect modification. */
|
|
#define CANARY_NAME "abcdefghijklmn"
|
|
|
|
/* On Linux the maximum length of the name of a task *including* the null
|
|
terminator. */
|
|
#define TASK_COMM_LEN 16
|
|
|
|
/* On Linux we can read this task's name from /proc. */
|
|
int
|
|
get_self_comm (long tid, char *buf, size_t len)
|
|
{
|
|
int res = 0;
|
|
#define FMT "/proc/self/task/%lu/comm"
|
|
char fname[sizeof (FMT) + 32];
|
|
sprintf (fname, FMT, (unsigned long) tid);
|
|
|
|
int fd = open (fname, O_RDONLY);
|
|
if (fd == -1)
|
|
return errno;
|
|
|
|
ssize_t n = read (fd, (void *) buf, len);
|
|
if (n < 0)
|
|
res = errno;
|
|
else
|
|
{
|
|
if (buf[n - 1] == '\n')
|
|
buf[n - 1] = '\0';
|
|
else if (n == len)
|
|
res = ERANGE;
|
|
else
|
|
buf[n] = '\0';
|
|
}
|
|
|
|
close (fd);
|
|
return res;
|
|
}
|
|
|
|
int
|
|
do_test (int argc, char **argv)
|
|
{
|
|
pthread_t self;
|
|
int res;
|
|
int ret = 0;
|
|
char name[TASK_COMM_LEN];
|
|
char name_check[TASK_COMM_LEN];
|
|
|
|
memset (name, '\0', TASK_COMM_LEN);
|
|
memset (name_check, '\0', TASK_COMM_LEN);
|
|
|
|
/* Test 1: Get the name of the task via pthread_getname_np and /proc
|
|
and verify that they both match. */
|
|
self = pthread_self ();
|
|
res = pthread_getname_np (self, name, TASK_COMM_LEN);
|
|
|
|
if (res == 0)
|
|
{
|
|
res = get_self_comm (gettid (), name_check, TASK_COMM_LEN);
|
|
|
|
if (res == 0)
|
|
{
|
|
if (strncmp (name, name_check, strlen (BIG_NAME)) == 0)
|
|
printf ("PASS: Test 1 - pthread_getname_np and /proc agree.\n");
|
|
else
|
|
{
|
|
printf ("FAIL: Test 1 - pthread_getname_np and /proc differ"
|
|
" i.e. %s != %s\n", name, name_check);
|
|
ret++;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
printf ("FAIL: Test 1 - unable read task name via proc.\n");
|
|
ret++;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
printf ("FAIL: Test 1 - pthread_getname_np failed with error %d\n", res);
|
|
ret++;
|
|
}
|
|
|
|
/* Test 2: Test setting the name and then independently verify it
|
|
was set. */
|
|
res = pthread_setname_np (self, NEW_NAME);
|
|
|
|
if (res == 0)
|
|
{
|
|
res = get_self_comm (gettid (), name_check, TASK_COMM_LEN);
|
|
if (res == 0)
|
|
{
|
|
if (strncmp (NEW_NAME, name_check, strlen (BIG_NAME)) == 0)
|
|
printf ("PASS: Test 2 - Value used in pthread_setname_np and"
|
|
" /proc agree.\n");
|
|
else
|
|
{
|
|
printf ("FAIL: Test 2 - Value used in pthread_setname_np"
|
|
" and /proc differ i.e. %s != %s\n",
|
|
NEW_NAME, name_check);
|
|
ret++;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
printf ("FAIL: Test 2 - unable to read task name via proc.\n");
|
|
ret++;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
printf ("FAIL: Test 2 - pthread_setname_np failed with error %d\n", res);
|
|
ret++;
|
|
}
|
|
|
|
/* Test 3: Test setting a name that is one-byte too big. */
|
|
res = pthread_getname_np (self, name, TASK_COMM_LEN);
|
|
|
|
if (res == 0)
|
|
{
|
|
res = pthread_setname_np (self, BIG_NAME);
|
|
if (res != 0)
|
|
{
|
|
if (res == ERANGE)
|
|
{
|
|
printf ("PASS: Test 3 - pthread_setname_np returned ERANGE"
|
|
" for a process name that was too long.\n");
|
|
|
|
/* Verify the old name didn't change. */
|
|
res = get_self_comm (gettid (), name_check, TASK_COMM_LEN);
|
|
if (res == 0)
|
|
{
|
|
if (strncmp (name, name_check, strlen (BIG_NAME)) == 0)
|
|
printf ("PASS: Test 3 - Original name unchanged after"
|
|
" pthread_setname_np returned ERANGE.\n");
|
|
else
|
|
{
|
|
printf ("FAIL: Test 3 - Original name changed after"
|
|
" pthread_setname_np returned ERANGE"
|
|
" i.e. %s != %s\n",
|
|
name, name_check);
|
|
ret++;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
printf ("FAIL: Test 3 - unable to read task name.\n");
|
|
ret++;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
printf ("FAIL: Test 3 - Wrong error returned"
|
|
" i.e. ERANGE != %d\n", res);
|
|
ret++;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
printf ("FAIL: Test 3 - Too-long name accepted by"
|
|
" pthread_setname_np.\n");
|
|
ret++;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
printf ("FAIL: Test 3 - Unable to get original name.\n");
|
|
ret++;
|
|
}
|
|
|
|
/* Test 4: Verify that setting the longest name works. */
|
|
res = pthread_setname_np (self, LONGEST_NAME);
|
|
|
|
if (res == 0)
|
|
{
|
|
res = get_self_comm (gettid (), name_check, TASK_COMM_LEN);
|
|
if (res == 0)
|
|
{
|
|
if (strncmp (LONGEST_NAME, name_check, strlen (BIG_NAME)) == 0)
|
|
printf ("PASS: Test 4 - Longest name set via pthread_setname_np"
|
|
" agrees with /proc.\n");
|
|
else
|
|
{
|
|
printf ("FAIL: Test 4 - Value used in pthread_setname_np and /proc"
|
|
" differ i.e. %s != %s\n", LONGEST_NAME, name_check);
|
|
ret++;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
printf ("FAIL: Test 4 - unable to read task name via proc.\n");
|
|
ret++;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
printf ("FAIL: Test 4 - pthread_setname_np failed with error %d\n", res);
|
|
ret++;
|
|
}
|
|
|
|
/* Test 5: Verify that getting a long name into a small buffer fails. */
|
|
strncpy (name, CANARY_NAME, strlen (CANARY_NAME) + 1);
|
|
|
|
/* Claim the buffer length is strlen (LONGEST_NAME). This is one character
|
|
too small to hold LONGEST_NAME *and* the null terminator. We should get
|
|
back ERANGE and name should be unmodified. */
|
|
res = pthread_getname_np (self, name, strlen (LONGEST_NAME));
|
|
|
|
if (res != 0)
|
|
{
|
|
if (res == ERANGE)
|
|
{
|
|
if (strncmp (CANARY_NAME, name, strlen (BIG_NAME)) == 0)
|
|
{
|
|
printf ("PASS: Test 5 - ERANGE and buffer unmodified.\n");
|
|
}
|
|
else
|
|
{
|
|
printf ("FAIL: Test 5 - Original buffer modified.\n");
|
|
ret++;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
printf ("FAIL: Test 5 - Did not return ERANGE for small buffer.\n");
|
|
ret++;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
printf ("FAIL: Test 5 - Returned name longer than buffer.\n");
|
|
ret++;
|
|
}
|
|
|
|
/* Test 6: Lastly make sure we can read back the longest name. */
|
|
res = pthread_getname_np (self, name, strlen (LONGEST_NAME) + 1);
|
|
|
|
if (res == 0)
|
|
{
|
|
if (strncmp (LONGEST_NAME, name, strlen (BIG_NAME)) == 0)
|
|
{
|
|
printf ("PASS: Test 6 - Read back longest name correctly.\n");
|
|
}
|
|
else
|
|
{
|
|
printf ("FAIL: Test 6 - Read \"%s\" instead of longest name.\n",
|
|
name);
|
|
ret++;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
printf ("FAIL: Test 6 - pthread_getname_np failed with error %d\n", res);
|
|
ret++;
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
#include <test-skeleton.c>
|