Merge "Make strerror(3) and strsignal(3) thread-safe, and add psignal(3) and psiginfo(3)."
This commit is contained in:
commit
fa36875df4
@ -61,7 +61,6 @@ libc_common_src_files := \
|
|||||||
unistd/sigwait.c \
|
unistd/sigwait.c \
|
||||||
unistd/sleep.c \
|
unistd/sleep.c \
|
||||||
unistd/statfs.c \
|
unistd/statfs.c \
|
||||||
unistd/strsignal.c \
|
|
||||||
unistd/syslog.c \
|
unistd/syslog.c \
|
||||||
unistd/system.c \
|
unistd/system.c \
|
||||||
unistd/tcgetpgrp.c \
|
unistd/tcgetpgrp.c \
|
||||||
@ -191,8 +190,6 @@ libc_common_src_files := \
|
|||||||
string/strcoll.c \
|
string/strcoll.c \
|
||||||
string/strcspn.c \
|
string/strcspn.c \
|
||||||
string/strdup.c \
|
string/strdup.c \
|
||||||
string/strerror.c \
|
|
||||||
string/strerror_r.c \
|
|
||||||
string/strlcat.c \
|
string/strlcat.c \
|
||||||
string/strlcpy.c \
|
string/strlcpy.c \
|
||||||
string/strncat.c \
|
string/strncat.c \
|
||||||
@ -291,6 +288,9 @@ libc_common_src_files := \
|
|||||||
bionic/sched_cpucount.c \
|
bionic/sched_cpucount.c \
|
||||||
bionic/semaphore.c \
|
bionic/semaphore.c \
|
||||||
bionic/sha1.c \
|
bionic/sha1.c \
|
||||||
|
bionic/strerror.cpp \
|
||||||
|
bionic/strerror_r.cpp \
|
||||||
|
bionic/strsignal.cpp \
|
||||||
bionic/stubs.cpp \
|
bionic/stubs.cpp \
|
||||||
bionic/system_properties.c \
|
bionic/system_properties.c \
|
||||||
bionic/tdestroy.c \
|
bionic/tdestroy.c \
|
||||||
@ -332,6 +332,7 @@ libc_common_src_files := \
|
|||||||
libc_upstream_netbsd_src_files := \
|
libc_upstream_netbsd_src_files := \
|
||||||
upstream-netbsd/libc/compat-43/creat.c \
|
upstream-netbsd/libc/compat-43/creat.c \
|
||||||
upstream-netbsd/libc/gen/nice.c \
|
upstream-netbsd/libc/gen/nice.c \
|
||||||
|
upstream-netbsd/libc/gen/psignal.c \
|
||||||
upstream-netbsd/libc/regex/regcomp.c \
|
upstream-netbsd/libc/regex/regcomp.c \
|
||||||
upstream-netbsd/libc/regex/regerror.c \
|
upstream-netbsd/libc/regex/regerror.c \
|
||||||
upstream-netbsd/libc/regex/regexec.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.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* 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
|
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
* SUCH DAMAGE.
|
* SUCH DAMAGE.
|
||||||
*/
|
*/
|
||||||
#include <signal.h>
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
char*
|
#include <string.h>
|
||||||
strsignal(int sig)
|
#include "ThreadLocalBuffer.h"
|
||||||
{
|
|
||||||
if ((unsigned)sig < NSIG)
|
GLOBAL_INIT_THREAD_LOCAL_BUFFER(strerror);
|
||||||
return (char*) sys_siglist[sig];
|
|
||||||
else
|
char* strerror(int error_number) {
|
||||||
return "Invalid signal 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 killpg(int pgrp, int sig);
|
||||||
extern int sigaltstack(const stack_t *ss, stack_t *oss);
|
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
|
__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.
|
* Copyright (c) 1983, 1993
|
||||||
* All rights reserved.
|
* The Regents of the University of California. All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
* modification, are permitted provided that the following conditions
|
* modification, are permitted provided that the following conditions
|
||||||
@ -28,14 +29,57 @@
|
|||||||
* SUCH DAMAGE.
|
* 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 <limits.h>
|
||||||
|
#include <signal.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
char *
|
#include "extern.h"
|
||||||
strerror(int num)
|
|
||||||
|
#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));
|
v = iov;
|
||||||
return (buf);
|
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 \
|
getcwd_test.cpp \
|
||||||
pthread_test.cpp \
|
pthread_test.cpp \
|
||||||
regex_test.cpp \
|
regex_test.cpp \
|
||||||
|
string_test.cpp \
|
||||||
|
|
||||||
test_dynamic_ldflags = -Wl,--export-dynamic -Wl,-u,DlSymTestFunction
|
test_dynamic_ldflags = -Wl,--export-dynamic -Wl,-u,DlSymTestFunction
|
||||||
test_dynamic_src_files = \
|
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