Merge "FORTIFY_SOURCE: don't define s?printf macros if already defined"
diff --git a/libc/bionic/libc_logging.cpp b/libc/bionic/libc_logging.cpp
index a4aeced..8e62e40 100644
--- a/libc/bionic/libc_logging.cpp
+++ b/libc/bionic/libc_logging.cpp
@@ -494,24 +494,27 @@
return __libc_write_stderr(tag, msg);
}
- iovec vec[5];
+ iovec vec[6];
char log_id = LOG_ID_MAIN;
vec[0].iov_base = &log_id;
vec[0].iov_len = sizeof(log_id);
+ uint16_t tid = gettid();
+ vec[1].iov_base = &tid;
+ vec[1].iov_len = sizeof(tid);
timespec ts;
clock_gettime(CLOCK_REALTIME, &ts);
log_time realtime_ts;
realtime_ts.tv_sec = ts.tv_sec;
realtime_ts.tv_nsec = ts.tv_nsec;
- vec[1].iov_base = &realtime_ts;
- vec[1].iov_len = sizeof(realtime_ts);
+ vec[2].iov_base = &realtime_ts;
+ vec[2].iov_len = sizeof(realtime_ts);
- vec[2].iov_base = &priority;
- vec[2].iov_len = 1;
- vec[3].iov_base = const_cast<char*>(tag);
- vec[3].iov_len = strlen(tag) + 1;
- vec[4].iov_base = const_cast<char*>(msg);
- vec[4].iov_len = strlen(msg) + 1;
+ vec[3].iov_base = &priority;
+ vec[3].iov_len = 1;
+ vec[4].iov_base = const_cast<char*>(tag);
+ vec[4].iov_len = strlen(tag) + 1;
+ vec[5].iov_base = const_cast<char*>(msg);
+ vec[5].iov_len = strlen(msg) + 1;
#else
int main_log_fd = TEMP_FAILURE_RETRY(open("/dev/log/main", O_CLOEXEC | O_WRONLY));
if (main_log_fd == -1) {
@@ -553,24 +556,27 @@
static int __libc_android_log_event(int32_t tag, char type, const void* payload, size_t len) {
#ifdef TARGET_USES_LOGD
- iovec vec[5];
+ iovec vec[6];
char log_id = LOG_ID_EVENTS;
vec[0].iov_base = &log_id;
vec[0].iov_len = sizeof(log_id);
+ uint16_t tid = gettid();
+ vec[1].iov_base = &tid;
+ vec[1].iov_len = sizeof(tid);
timespec ts;
clock_gettime(CLOCK_REALTIME, &ts);
log_time realtime_ts;
realtime_ts.tv_sec = ts.tv_sec;
realtime_ts.tv_nsec = ts.tv_nsec;
- vec[1].iov_base = &realtime_ts;
- vec[1].iov_len = sizeof(realtime_ts);
+ vec[2].iov_base = &realtime_ts;
+ vec[2].iov_len = sizeof(realtime_ts);
- vec[2].iov_base = &tag;
- vec[2].iov_len = sizeof(tag);
- vec[3].iov_base = &type;
- vec[3].iov_len = sizeof(type);
- vec[4].iov_base = const_cast<void*>(payload);
- vec[4].iov_len = len;
+ vec[3].iov_base = &tag;
+ vec[3].iov_len = sizeof(tag);
+ vec[4].iov_base = &type;
+ vec[4].iov_len = sizeof(type);
+ vec[5].iov_base = const_cast<void*>(payload);
+ vec[5].iov_len = len;
int event_log_fd = __libc_open_log_socket();
#else
diff --git a/libc/bionic/posix_timers.cpp b/libc/bionic/posix_timers.cpp
index ffe213c..e9190b2 100644
--- a/libc/bionic/posix_timers.cpp
+++ b/libc/bionic/posix_timers.cpp
@@ -100,11 +100,14 @@
static void __timer_thread_stop(PosixTimer* timer) {
pthread_kill(timer->callback_thread, TIMER_SIGNAL);
- // We can't pthread_join because POSIX says "the threads created in response to a timer
- // expiration are created detached, or in an unspecified way if the thread attribute's
- // detachstate is PTHREAD_CREATE_JOINABLE".
- while (timer->exiting == 0) {
- __futex_wait(&timer->exiting, 0, NULL);
+ // If this is being called from within the callback thread, do nothing else.
+ if (pthread_self() != timer->callback_thread) {
+ // We can't pthread_join because POSIX says "the threads created in response to a timer
+ // expiration are created detached, or in an unspecified way if the thread attribute's
+ // detachstate is PTHREAD_CREATE_JOINABLE".
+ while (timer->exiting == 0) {
+ __futex_wait(&timer->exiting, 0, NULL);
+ }
}
}
diff --git a/tests/Android.mk b/tests/Android.mk
index 451b3a9..8dffa2f 100644
--- a/tests/Android.mk
+++ b/tests/Android.mk
@@ -248,11 +248,12 @@
# gtest needs ANDROID_DATA/local/tmp for death test output.
# Make sure to create ANDROID_DATA/local/tmp if doesn't exist.
# Use the current target out directory as ANDROID_DATA.
+# BIONIC_TEST_FLAGS is either empty or it comes from the user.
bionic-unit-tests-glibc-run: bionic-unit-tests-glibc
mkdir -p $(TARGET_OUT_DATA)/local/tmp
ANDROID_DATA=$(TARGET_OUT_DATA) \
ANDROID_ROOT=$(TARGET_OUT) \
- $(HOST_OUT_EXECUTABLES)/bionic-unit-tests-glibc
+ $(HOST_OUT_EXECUTABLES)/bionic-unit-tests-glibc $(BIONIC_TEST_FLAGS)
# -----------------------------------------------------------------------------
# Run the unit tests built against x86 bionic on an x86 host.
@@ -267,6 +268,7 @@
# gtest needs ANDROID_DATA/local/tmp for death test output.
# Make sure to create ANDROID_DATA/local/tmp if doesn't exist.
# bionic itself should always work relative to ANDROID_DATA or ANDROID_ROOT.
+# BIONIC_TEST_FLAGS is either empty or it comes from the user.
bionic-unit-tests-run-on-host: bionic-unit-tests $(TARGET_OUT_EXECUTABLES)/$(LINKER) $(TARGET_OUT_EXECUTABLES)/sh
if [ ! -d /system -o ! -d /system/bin ]; then \
echo "Attempting to create /system/bin"; \
@@ -278,7 +280,7 @@
ANDROID_DATA=$(TARGET_OUT_DATA) \
ANDROID_ROOT=$(TARGET_OUT) \
LD_LIBRARY_PATH=$(TARGET_OUT_SHARED_LIBRARIES) \
- $(TARGET_OUT_DATA_NATIVE_TESTS)/bionic-unit-tests/bionic-unit-tests
+ $(TARGET_OUT_DATA_NATIVE_TESTS)/bionic-unit-tests/bionic-unit-tests $(BIONIC_TEST_FLAGS)
endif
endif
diff --git a/tests/time_test.cpp b/tests/time_test.cpp
index af6ae85..26b7775 100644
--- a/tests/time_test.cpp
+++ b/tests/time_test.cpp
@@ -341,3 +341,49 @@
EXPECT_EQ(1, counter2.value);
EXPECT_EQ(0, counter3.value);
}
+
+struct TimerDeleteData {
+ timer_t timer_id;
+ pthread_t thread_id;
+ volatile bool complete;
+};
+
+static void TimerDeleteCallback(sigval_t value) {
+ TimerDeleteData* tdd = reinterpret_cast<TimerDeleteData*>(value.sival_ptr);
+
+ tdd->thread_id = pthread_self();
+ timer_delete(tdd->timer_id);
+ tdd->complete = true;
+}
+
+TEST(time, timer_delete_from_timer_thread) {
+ TimerDeleteData tdd;
+ sigevent_t se;
+
+ memset(&se, 0, sizeof(se));
+ se.sigev_notify = SIGEV_THREAD;
+ se.sigev_notify_function = TimerDeleteCallback;
+ se.sigev_value.sival_ptr = &tdd;
+
+ tdd.complete = false;
+ ASSERT_EQ(0, timer_create(CLOCK_REALTIME, &se, &tdd.timer_id));
+
+ itimerspec ts;
+ ts.it_value.tv_sec = 0;
+ ts.it_value.tv_nsec = 100;
+ ts.it_interval.tv_sec = 0;
+ ts.it_interval.tv_nsec = 0;
+ ASSERT_EQ(0, timer_settime(tdd.timer_id, TIMER_ABSTIME, &ts, NULL));
+
+ time_t cur_time = time(NULL);
+ while (!tdd.complete && (time(NULL) - cur_time) < 5);
+ ASSERT_TRUE(tdd.complete);
+
+#if defined(__BIONIC__)
+ // Since bionic timers are implemented by creating a thread to handle the
+ // callback, verify that the thread actually completes.
+ cur_time = time(NULL);
+ while (pthread_detach(tdd.thread_id) != ESRCH && (time(NULL) - cur_time) < 5);
+ ASSERT_EQ(ESRCH, pthread_detach(tdd.thread_id));
+#endif
+}