am fa36875d
: Merge "Make strerror(3) and strsignal(3) thread-safe, and add psignal(3) and psiginfo(3)."
* commit 'fa36875df423af968d053c584c0de18a2448516b': Make strerror(3) and strsignal(3) thread-safe, and add psignal(3) and psiginfo(3).
This commit is contained in:
commit
de9db8f7ef
@ -61,7 +61,6 @@ libc_common_src_files := \
|
||||
unistd/sigwait.c \
|
||||
unistd/sleep.c \
|
||||
unistd/statfs.c \
|
||||
unistd/strsignal.c \
|
||||
unistd/syslog.c \
|
||||
unistd/system.c \
|
||||
unistd/tcgetpgrp.c \
|
||||
@ -191,8 +190,6 @@ libc_common_src_files := \
|
||||
string/strcoll.c \
|
||||
string/strcspn.c \
|
||||
string/strdup.c \
|
||||
string/strerror.c \
|
||||
string/strerror_r.c \
|
||||
string/strlcat.c \
|
||||
string/strlcpy.c \
|
||||
string/strncat.c \
|
||||
@ -291,6 +288,9 @@ libc_common_src_files := \
|
||||
bionic/sched_cpucount.c \
|
||||
bionic/semaphore.c \
|
||||
bionic/sha1.c \
|
||||
bionic/strerror.cpp \
|
||||
bionic/strerror_r.cpp \
|
||||
bionic/strsignal.cpp \
|
||||
bionic/stubs.cpp \
|
||||
bionic/system_properties.c \
|
||||
bionic/tdestroy.c \
|
||||
@ -332,6 +332,7 @@ libc_common_src_files := \
|
||||
libc_upstream_netbsd_src_files := \
|
||||
upstream-netbsd/libc/compat-43/creat.c \
|
||||
upstream-netbsd/libc/gen/nice.c \
|
||||
upstream-netbsd/libc/gen/psignal.c \
|
||||
upstream-netbsd/libc/regex/regcomp.c \
|
||||
upstream-netbsd/libc/regex/regerror.c \
|
||||
upstream-netbsd/libc/regex/regexec.c \
|
||||
|
59
libc/bionic/ThreadLocalBuffer.h
Normal file
59
libc/bionic/ThreadLocalBuffer.h
Normal file
@ -0,0 +1,59 @@
|
||||
/*
|
||||
* Copyright (C) 2012 The Android Open Source Project
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
|
||||
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef _BIONIC_THREAD_LOCAL_BUFFER_H_included
|
||||
#define _BIONIC_THREAD_LOCAL_BUFFER_H_included
|
||||
|
||||
#include <malloc.h>
|
||||
#include <pthread.h>
|
||||
|
||||
// libstdc++ currently contains __cxa_guard_acquire and __cxa_guard_release,
|
||||
// so we make do with macros instead of a C++ class.
|
||||
// TODO: move __cxa_guard_acquire and __cxa_guard_release into libc.
|
||||
|
||||
#define GLOBAL_INIT_THREAD_LOCAL_BUFFER(name) \
|
||||
static pthread_once_t name ## _once; \
|
||||
static pthread_key_t name ## _key; \
|
||||
static void name ## _key_destroy(void* buffer) { \
|
||||
free(buffer); \
|
||||
} \
|
||||
static void name ## _key_init() { \
|
||||
pthread_key_create(&name ## _key, name ## _key_destroy); \
|
||||
}
|
||||
|
||||
// Leaves "name_buffer" and "name_byte_count" defined and initialized.
|
||||
#define LOCAL_INIT_THREAD_LOCAL_BUFFER(type, name, byte_count) \
|
||||
pthread_once(&name ## _once, name ## _key_init); \
|
||||
type name ## _buffer = reinterpret_cast<type>(pthread_getspecific(name ## _key)); \
|
||||
if (name ## _buffer == NULL) { \
|
||||
name ## _buffer = reinterpret_cast<type>(malloc(byte_count)); \
|
||||
pthread_setspecific(name ## _key, name ## _buffer); \
|
||||
} \
|
||||
const size_t name ## _buffer_size = byte_count
|
||||
|
||||
#endif // _BIONIC_THREAD_LOCAL_BUFFER_H_included
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2008 The Android Open Source Project
|
||||
* Copyright (C) 2012 The Android Open Source Project
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@ -25,14 +25,14 @@
|
||||
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
#include <signal.h>
|
||||
#include <string.h>
|
||||
|
||||
char*
|
||||
strsignal(int sig)
|
||||
{
|
||||
if ((unsigned)sig < NSIG)
|
||||
return (char*) sys_siglist[sig];
|
||||
else
|
||||
return "Invalid signal number";
|
||||
#include <string.h>
|
||||
#include "ThreadLocalBuffer.h"
|
||||
|
||||
GLOBAL_INIT_THREAD_LOCAL_BUFFER(strerror);
|
||||
|
||||
char* strerror(int error_number) {
|
||||
LOCAL_INIT_THREAD_LOCAL_BUFFER(char*, strerror, NL_TEXTMAX);
|
||||
strerror_r(error_number, strerror_buffer, strerror_buffer_size);
|
||||
return strerror_buffer;
|
||||
}
|
71
libc/bionic/strerror_r.cpp
Normal file
71
libc/bionic/strerror_r.cpp
Normal file
@ -0,0 +1,71 @@
|
||||
/* $OpenBSD: strerror_r.c,v 1.6 2005/08/08 08:05:37 espie Exp $ */
|
||||
/* Public Domain <marc@snafu.org> */
|
||||
|
||||
#include <errno.h>
|
||||
#include <limits.h>
|
||||
#include <signal.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
struct Pair {
|
||||
int code;
|
||||
const char* msg;
|
||||
};
|
||||
|
||||
static const char* __code_string_lookup(const Pair* strings, int code) {
|
||||
for (size_t i = 0; strings[i].msg != NULL; ++i) {
|
||||
if (strings[i].code == code) {
|
||||
return strings[i].msg;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static const Pair _sys_error_strings[] = {
|
||||
#define __BIONIC_ERRDEF(x,y,z) { x, z },
|
||||
#include <sys/_errdefs.h>
|
||||
{ 0, NULL }
|
||||
};
|
||||
|
||||
int strerror_r(int error_number, char* buf, size_t buf_len) {
|
||||
int saved_errno = errno;
|
||||
size_t length;
|
||||
|
||||
const char* error_name = __code_string_lookup(_sys_error_strings, error_number);
|
||||
if (error_name != NULL) {
|
||||
length = snprintf(buf, buf_len, "%s", error_name);
|
||||
} else {
|
||||
length = snprintf(buf, buf_len, "Unknown error %u", error_number);
|
||||
}
|
||||
if (length >= buf_len) {
|
||||
errno = ERANGE;
|
||||
return -1;
|
||||
}
|
||||
|
||||
errno = saved_errno;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const Pair _sys_signal_strings[] = {
|
||||
#define __BIONIC_SIGDEF(x,y,z) { y, z },
|
||||
#include <sys/_sigdefs.h>
|
||||
{ 0, NULL }
|
||||
};
|
||||
|
||||
extern "C" const char* __strsignal(int signal_number, char* buf, size_t buf_len) {
|
||||
const char* signal_name = __code_string_lookup(_sys_signal_strings, signal_number);
|
||||
if (signal_name != NULL) {
|
||||
return signal_name;
|
||||
}
|
||||
|
||||
const char* prefix = "Unknown";
|
||||
if (signal_number >= SIGRTMIN && signal_number <= SIGRTMAX) {
|
||||
prefix = "Real-time";
|
||||
signal_number -= SIGRTMIN;
|
||||
}
|
||||
size_t length = snprintf(buf, buf_len, "%s signal %d", prefix, signal_number);
|
||||
if (length >= buf_len) {
|
||||
return NULL;
|
||||
}
|
||||
return buf;
|
||||
}
|
39
libc/bionic/strsignal.cpp
Normal file
39
libc/bionic/strsignal.cpp
Normal file
@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Copyright (C) 2012 The Android Open Source Project
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
|
||||
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include "ThreadLocalBuffer.h"
|
||||
|
||||
extern "C" const char* __strsignal(int, char*, size_t);
|
||||
|
||||
GLOBAL_INIT_THREAD_LOCAL_BUFFER(strsignal);
|
||||
|
||||
char* strsignal(int signal_number) {
|
||||
LOCAL_INIT_THREAD_LOCAL_BUFFER(char*, strsignal, NL_TEXTMAX);
|
||||
return const_cast<char*>(__strsignal(signal_number, strsignal_buffer, strsignal_buffer_size));
|
||||
}
|
@ -125,6 +125,8 @@ extern int kill(pid_t, int);
|
||||
extern int killpg(int pgrp, int sig);
|
||||
extern int sigaltstack(const stack_t *ss, stack_t *oss);
|
||||
|
||||
extern void psiginfo(const siginfo_t* si, const char* message);
|
||||
extern void psignal(int signal_number, const char* message);
|
||||
|
||||
__END_DECLS
|
||||
|
||||
|
@ -1,163 +0,0 @@
|
||||
/* $OpenBSD: strerror_r.c,v 1.6 2005/08/08 08:05:37 espie Exp $ */
|
||||
/* Public Domain <marc@snafu.org> */
|
||||
|
||||
#define sys_siglist _sys_siglist
|
||||
|
||||
#include <errno.h>
|
||||
#include <limits.h>
|
||||
#include <signal.h>
|
||||
#include <string.h>
|
||||
|
||||
typedef struct {
|
||||
int code;
|
||||
const char* msg;
|
||||
} CodeString;
|
||||
|
||||
static const char*
|
||||
__code_string_lookup( const CodeString* strings,
|
||||
int code )
|
||||
{
|
||||
int nn = 0;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
if (strings[nn].msg == NULL)
|
||||
break;
|
||||
|
||||
if (strings[nn].code == code)
|
||||
return strings[nn].msg;
|
||||
|
||||
nn++;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
static const CodeString _sys_error_strings[] =
|
||||
{
|
||||
#define __BIONIC_ERRDEF(x,y,z) { x, z },
|
||||
#include <sys/_errdefs.h>
|
||||
{ 0, NULL }
|
||||
};
|
||||
|
||||
static size_t
|
||||
__digits10(unsigned int num)
|
||||
{
|
||||
size_t i = 0;
|
||||
|
||||
do {
|
||||
num /= 10;
|
||||
i++;
|
||||
} while (num != 0);
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
static int
|
||||
__itoa(int num, int sign, char *buffer, size_t start, size_t end)
|
||||
{
|
||||
size_t pos;
|
||||
unsigned int a;
|
||||
int neg;
|
||||
|
||||
if (sign && num < 0) {
|
||||
a = -num;
|
||||
neg = 1;
|
||||
}
|
||||
else {
|
||||
a = num;
|
||||
neg = 0;
|
||||
}
|
||||
|
||||
pos = start + __digits10(a);
|
||||
if (neg)
|
||||
pos++;
|
||||
|
||||
if (pos < end)
|
||||
buffer[pos] = '\0';
|
||||
else
|
||||
return ERANGE;
|
||||
pos--;
|
||||
do {
|
||||
buffer[pos] = (a % 10) + '0';
|
||||
pos--;
|
||||
a /= 10;
|
||||
} while (a != 0);
|
||||
if (neg)
|
||||
buffer[pos] = '-';
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
strerror_r(int errnum, char *strerrbuf, size_t buflen)
|
||||
{
|
||||
int save_errno;
|
||||
int len, ret = 0;
|
||||
const char* msg;
|
||||
|
||||
save_errno = errno;
|
||||
msg = __code_string_lookup( _sys_error_strings, errnum );
|
||||
if (msg != NULL) {
|
||||
len = strlcpy(strerrbuf, msg, buflen);
|
||||
if ((size_t)len >= buflen)
|
||||
ret = ERANGE;
|
||||
} else {
|
||||
len = strlcpy(strerrbuf, "Unknown error: ", buflen);
|
||||
if ((size_t)len >= buflen)
|
||||
ret = ERANGE;
|
||||
else {
|
||||
int ret = __itoa(errnum, 1, strerrbuf, len, buflen);
|
||||
|
||||
if (ret == 0)
|
||||
ret = EINVAL;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
#if 0
|
||||
static const CodeString _sys_signal_strings[] =
|
||||
{
|
||||
#define SIGDEF(x,y,z) { y, z },
|
||||
#include <sys/_sigdefs.h>
|
||||
};
|
||||
|
||||
|
||||
static int
|
||||
__num2string(int num, int sign, int setid, char *buf, size_t buflen,
|
||||
char * list[], size_t max, const char *def)
|
||||
{
|
||||
int ret = 0;
|
||||
size_t len;
|
||||
|
||||
if (0 <= num && num < max) {
|
||||
len = strlcpy(buf, def, buflen);
|
||||
if (len >= buflen)
|
||||
ret = ERANGE;
|
||||
} else {
|
||||
len = strlcpy(buf, def, buflen);
|
||||
if (len >= buflen)
|
||||
ret = ERANGE;
|
||||
else {
|
||||
ret = __itoa(num, sign, buf, len, buflen);
|
||||
if (ret == 0)
|
||||
ret = EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
|
||||
#define USIGPREFIX "Unknown signal: "
|
||||
|
||||
char *
|
||||
__strsignal(int num, char *buf)
|
||||
{
|
||||
__num2string(num, 0, 2, buf, NL_TEXTMAX, (char **)sys_siglist, NSIG,
|
||||
USIGPREFIX);
|
||||
return buf;
|
||||
}
|
||||
#endif
|
22
libc/upstream-netbsd/extern.h
Normal file
22
libc/upstream-netbsd/extern.h
Normal file
@ -0,0 +1,22 @@
|
||||
/*
|
||||
* Copyright (C) 2012 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef _BIONIC_NETBSD_EXTERN_H_included
|
||||
#define _BIONIC_NETBSD_EXTERN_H_included
|
||||
|
||||
// Placeholder.
|
||||
|
||||
#endif
|
@ -1,7 +1,8 @@
|
||||
/* $OpenBSD: strerror.c,v 1.7 2005/08/08 08:05:37 espie Exp $ */
|
||||
/* $NetBSD: psignal.c,v 1.23 2012/03/13 21:13:36 christos Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1988 Regents of the University of California.
|
||||
* All rights reserved.
|
||||
* Copyright (c) 1983, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
@ -28,14 +29,57 @@
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include <sys/cdefs.h>
|
||||
#if defined(LIBC_SCCS) && !defined(lint)
|
||||
#if 0
|
||||
static char sccsid[] = "@(#)psignal.c 8.1 (Berkeley) 6/4/93";
|
||||
#else
|
||||
__RCSID("$NetBSD: psignal.c,v 1.23 2012/03/13 21:13:36 christos Exp $");
|
||||
#endif
|
||||
#endif /* LIBC_SCCS and not lint */
|
||||
|
||||
#include "namespace.h"
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/uio.h>
|
||||
|
||||
#include <limits.h>
|
||||
#include <signal.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
char *
|
||||
strerror(int num)
|
||||
#include "extern.h"
|
||||
|
||||
#ifdef __weak_alias
|
||||
__weak_alias(psignal,_psignal)
|
||||
#endif
|
||||
|
||||
void
|
||||
psignal(int sig, const char *s)
|
||||
{
|
||||
static char buf[256];
|
||||
struct iovec *v;
|
||||
struct iovec iov[4];
|
||||
char buf[NL_TEXTMAX];
|
||||
|
||||
(void)strerror_r(num, buf, sizeof(buf));
|
||||
return (buf);
|
||||
v = iov;
|
||||
if (s && *s) {
|
||||
v->iov_base = __UNCONST(s);
|
||||
v->iov_len = strlen(s);
|
||||
v++;
|
||||
v->iov_base = __UNCONST(": ");
|
||||
v->iov_len = 2;
|
||||
v++;
|
||||
}
|
||||
v->iov_base = __UNCONST(__strsignal((int)sig, buf, sizeof(buf)));
|
||||
v->iov_len = strlen(v->iov_base);
|
||||
v++;
|
||||
v->iov_base = __UNCONST("\n");
|
||||
v->iov_len = 1;
|
||||
(void)writev(STDERR_FILENO, iov, (int)((v - iov) + 1));
|
||||
}
|
||||
|
||||
void
|
||||
psiginfo(const siginfo_t *si, const char *s)
|
||||
{
|
||||
psignal(si->si_signo, s);
|
||||
}
|
@ -22,6 +22,7 @@ test_src_files = \
|
||||
getcwd_test.cpp \
|
||||
pthread_test.cpp \
|
||||
regex_test.cpp \
|
||||
string_test.cpp \
|
||||
|
||||
test_dynamic_ldflags = -Wl,--export-dynamic -Wl,-u,DlSymTestFunction
|
||||
test_dynamic_src_files = \
|
||||
|
107
tests/string_test.cpp
Normal file
107
tests/string_test.cpp
Normal file
@ -0,0 +1,107 @@
|
||||
/*
|
||||
* Copyright (C) 2012 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
|
||||
TEST(string, strerror) {
|
||||
// Valid.
|
||||
ASSERT_STREQ("Success", strerror(0));
|
||||
ASSERT_STREQ("Operation not permitted", strerror(1));
|
||||
|
||||
// Invalid.
|
||||
ASSERT_STREQ("Unknown error 4294967295", strerror(-1));
|
||||
ASSERT_STREQ("Unknown error 1234", strerror(1234));
|
||||
}
|
||||
|
||||
void* ConcurrentStrErrorFn(void* arg) {
|
||||
bool equal = (strcmp("Unknown error 2002", strerror(2002)) == 0);
|
||||
return reinterpret_cast<void*>(equal);
|
||||
}
|
||||
|
||||
#if __BIONIC__ // glibc's strerror isn't thread safe, only its strsignal.
|
||||
TEST(string, strerror_concurrent) {
|
||||
const char* strerror1001 = strerror(1001);
|
||||
ASSERT_STREQ("Unknown error 1001", strerror1001);
|
||||
|
||||
pthread_t t;
|
||||
ASSERT_EQ(0, pthread_create(&t, NULL, ConcurrentStrErrorFn, NULL));
|
||||
void* result;
|
||||
ASSERT_EQ(0, pthread_join(t, &result));
|
||||
ASSERT_TRUE(static_cast<bool>(result));
|
||||
|
||||
ASSERT_STREQ("Unknown error 1001", strerror1001);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if __BIONIC__ // glibc's strerror_r doesn't even have the same signature as the POSIX one.
|
||||
TEST(string, strerror_r) {
|
||||
char buf[256];
|
||||
|
||||
// Valid.
|
||||
ASSERT_EQ(0, strerror_r(0, buf, sizeof(buf)));
|
||||
ASSERT_STREQ("Success", buf);
|
||||
ASSERT_EQ(0, strerror_r(1, buf, sizeof(buf)));
|
||||
ASSERT_STREQ("Operation not permitted", buf);
|
||||
|
||||
// Invalid.
|
||||
ASSERT_EQ(0, strerror_r(-1, buf, sizeof(buf)));
|
||||
ASSERT_STREQ("Unknown error 4294967295", buf);
|
||||
ASSERT_EQ(0, strerror_r(1234, buf, sizeof(buf)));
|
||||
ASSERT_STREQ("Unknown error 1234", buf);
|
||||
|
||||
// Buffer too small.
|
||||
ASSERT_EQ(-1, strerror_r(0, buf, 2));
|
||||
ASSERT_EQ(ERANGE, errno);
|
||||
}
|
||||
#endif
|
||||
|
||||
TEST(string, strsignal) {
|
||||
// A regular signal.
|
||||
ASSERT_STREQ("Hangup", strsignal(1));
|
||||
|
||||
// A real-time signal.
|
||||
#ifdef __GLIBC__ // glibc reserves real-time signals for internal use, and doesn't count those.
|
||||
ASSERT_STREQ("Real-time signal 14", strsignal(48));
|
||||
#else
|
||||
ASSERT_STREQ("Real-time signal 16", strsignal(48));
|
||||
#endif
|
||||
|
||||
// Errors.
|
||||
ASSERT_STREQ("Unknown signal -1", strsignal(-1)); // Too small.
|
||||
ASSERT_STREQ("Unknown signal 0", strsignal(0)); // Still too small.
|
||||
ASSERT_STREQ("Unknown signal 1234", strsignal(1234)); // Too large.
|
||||
}
|
||||
|
||||
void* ConcurrentStrSignalFn(void* arg) {
|
||||
bool equal = (strcmp("Unknown signal 2002", strsignal(2002)) == 0);
|
||||
return reinterpret_cast<void*>(equal);
|
||||
}
|
||||
|
||||
TEST(string, strsignal_concurrent) {
|
||||
const char* strsignal1001 = strsignal(1001);
|
||||
ASSERT_STREQ("Unknown signal 1001", strsignal1001);
|
||||
|
||||
pthread_t t;
|
||||
ASSERT_EQ(0, pthread_create(&t, NULL, ConcurrentStrSignalFn, NULL));
|
||||
void* result;
|
||||
ASSERT_EQ(0, pthread_join(t, &result));
|
||||
ASSERT_TRUE(static_cast<bool>(result));
|
||||
|
||||
ASSERT_STREQ("Unknown signal 1001", strsignal1001);
|
||||
}
|
Loading…
Reference in New Issue
Block a user