Merge "Improve detection of already loaded libraries"
diff --git a/libc/bionic/system_properties.cpp b/libc/bionic/system_properties.cpp
index ec3d04b..97e1a03 100644
--- a/libc/bionic/system_properties.cpp
+++ b/libc/bionic/system_properties.cpp
@@ -655,23 +655,6 @@
return 0;
}
-int __system_property_wait(const prop_info *pi)
-{
- if (pi == 0) {
- prop_area *pa = __system_property_area__;
- const uint32_t n = pa->serial;
- do {
- __futex_wait(&pa->serial, n, NULL);
- } while (n == pa->serial);
- } else {
- const uint32_t n = pi->serial;
- do {
- __futex_wait((volatile void *)&pi->serial, n, NULL);
- } while (n == pi->serial);
- }
- return 0;
-}
-
int __system_property_update(prop_info *pi, const char *value, unsigned int len)
{
prop_area *pa = __system_property_area__;
diff --git a/libc/include/pthread.h b/libc/include/pthread.h
index 7b8de81..49f943a 100644
--- a/libc/include/pthread.h
+++ b/libc/include/pthread.h
@@ -35,7 +35,7 @@
#include <limits.h>
#include <sys/types.h>
-#ifdef __LP64__
+#if defined(__LP64__)
#define __RESERVED_INITIALIZER , {0}
#else
#define __RESERVED_INITIALIZER
@@ -112,7 +112,11 @@
#define PTHREAD_ONCE_INIT 0
+#if defined(__LP64__)
+#define PTHREAD_STACK_MIN (4 * PAGE_SIZE)
+#else
#define PTHREAD_STACK_MIN (2 * PAGE_SIZE)
+#endif
#define PTHREAD_CREATE_DETACHED 0x00000001
#define PTHREAD_CREATE_JOINABLE 0x00000000
diff --git a/libc/include/sys/ucontext.h b/libc/include/sys/ucontext.h
index 3737cbe..f150ac7 100644
--- a/libc/include/sys/ucontext.h
+++ b/libc/include/sys/ucontext.h
@@ -150,7 +150,8 @@
stack_t uc_stack;
mcontext_t uc_mcontext;
sigset_t uc_sigmask;
- /* TODO: __fpregs_mem? */
+ char __padding[128 - sizeof(sigset_t)];
+ struct _libc_fpstate __fpregs_mem;
} ucontext_t;
#elif defined(__mips__)
@@ -238,7 +239,31 @@
typedef long greg_t;
typedef greg_t gregset_t[NGREG];
-typedef struct user_i387_struct* fpregset_t;
+struct _libc_fpxreg {
+ unsigned short significand[4];
+ unsigned short exponent;
+ unsigned short padding[3];
+};
+
+struct _libc_xmmreg {
+ uint32_t element[4];
+};
+
+struct _libc_fpstate {
+ uint16_t cwd;
+ uint16_t swd;
+ uint16_t ftw;
+ uint16_t fop;
+ uint64_t rip;
+ uint64_t rdp;
+ uint32_t mxcsr;
+ uint32_t mxcr_mask;
+ struct _libc_fpxreg _st[8];
+ struct _libc_xmmreg _xmm[16];
+ uint32_t padding[24];
+};
+
+typedef struct _libc_fpstate* fpregset_t;
typedef struct {
gregset_t gregs;
@@ -252,7 +277,8 @@
stack_t uc_stack;
mcontext_t uc_mcontext;
sigset_t uc_sigmask;
- /* TODO: __fpregs_mem? */
+ char __padding[128 - sizeof(sigset_t)];
+ struct _libc_fpstate __fpregs_mem;
} ucontext_t;
#endif
diff --git a/libc/tzcode/localtime.c b/libc/tzcode/localtime.c
index 9f67dc6..c40569c 100644
--- a/libc/tzcode/localtime.c
+++ b/libc/tzcode/localtime.c
@@ -506,37 +506,41 @@
if (doextend && nread > 2 &&
up->buf[0] == '\n' && up->buf[nread - 1] == '\n' &&
sp->typecnt + 2 <= TZ_MAX_TYPES) {
- struct state ts;
+ struct state * ts = malloc(sizeof *ts);
register int result;
+ if (ts == NULL)
+ goto oops;
+
up->buf[nread - 1] = '\0';
- result = tzparse(&up->buf[1], &ts, FALSE);
- if (result == 0 && ts.typecnt == 2 &&
- sp->charcnt + ts.charcnt <= TZ_MAX_CHARS) {
+ result = tzparse(&up->buf[1], ts, FALSE);
+ if (result == 0 && ts->typecnt == 2 &&
+ sp->charcnt + ts->charcnt <= TZ_MAX_CHARS) {
for (i = 0; i < 2; ++i)
- ts.ttis[i].tt_abbrind +=
+ ts->ttis[i].tt_abbrind +=
sp->charcnt;
- for (i = 0; i < ts.charcnt; ++i)
+ for (i = 0; i < ts->charcnt; ++i)
sp->chars[sp->charcnt++] =
- ts.chars[i];
+ ts->chars[i];
i = 0;
- while (i < ts.timecnt &&
- ts.ats[i] <=
+ while (i < ts->timecnt &&
+ ts->ats[i] <=
sp->ats[sp->timecnt - 1])
++i;
- while (i < ts.timecnt &&
+ while (i < ts->timecnt &&
sp->timecnt < TZ_MAX_TIMES) {
sp->ats[sp->timecnt] =
- ts.ats[i];
+ ts->ats[i];
sp->types[sp->timecnt] =
sp->typecnt +
- ts.types[i];
+ ts->types[i];
++sp->timecnt;
++i;
}
- sp->ttis[sp->typecnt++] = ts.ttis[0];
- sp->ttis[sp->typecnt++] = ts.ttis[1];
+ sp->ttis[sp->typecnt++] = ts->ttis[0];
+ sp->ttis[sp->typecnt++] = ts->ttis[1];
}
+ free(ts);
}
if (sp->timecnt > 1) {
for (i = 1; i < sp->timecnt; ++i)
@@ -2280,22 +2284,33 @@
// Non-standard API: mktime(3) but with an explicit timezone parameter.
time_t mktime_tz(struct tm* const tmp, const char* tz) {
- struct state st;
- if (__bionic_tzload_cached(tz, &st, TRUE) != 0) {
+ struct state* st = malloc(sizeof(*st));
+ time_t return_value;
+
+ if (st == NULL)
+ return 0;
+ if (__bionic_tzload_cached(tz, st, TRUE) != 0) {
// TODO: not sure what's best here, but for now, we fall back to gmt.
- gmtload(&st);
+ gmtload(st);
}
- return time1(tmp, localsub, 0L, &st);
+
+ return_value = time1(tmp, localsub, 0L, st);
+ free(st);
+ return return_value;
}
// Non-standard API: localtime(3) but with an explicit timezone parameter.
void localtime_tz(const time_t* const timep, struct tm* tmp, const char* tz) {
- struct state st;
- if (__bionic_tzload_cached(tz, &st, TRUE) != 0) {
+ struct state* st = malloc(sizeof(*st));
+
+ if (st == NULL)
+ return;
+ if (__bionic_tzload_cached(tz, st, TRUE) != 0) {
// TODO: not sure what's best here, but for now, we fall back to gmt.
- gmtload(&st);
+ gmtload(st);
}
- localsub(timep, 0L, tmp, &st);
+ localsub(timep, 0L, tmp, st);
+ free(st);
}
// END android-added
diff --git a/tests/stdio_test.cpp b/tests/stdio_test.cpp
index 2a0549a..4990582 100644
--- a/tests/stdio_test.cpp
+++ b/tests/stdio_test.cpp
@@ -17,6 +17,7 @@
#include <gtest/gtest.h>
#include <errno.h>
+#include <fcntl.h>
#include <limits.h>
#include <math.h>
#include <stdio.h>
@@ -407,6 +408,28 @@
EXPECT_STREQ("-0.000000", buf);
}
+TEST(stdio, fprintf_failures_7229520) {
+ FILE* fp;
+
+ // Unbuffered case where the fprintf(3) itself fails.
+ ASSERT_NE(nullptr, fp = tmpfile());
+ setbuf(fp, NULL);
+ ASSERT_EQ(4, fprintf(fp, "epic"));
+ ASSERT_EQ(0, close(fileno(fp)));
+ ASSERT_EQ(-1, fprintf(fp, "fail"));
+ ASSERT_EQ(-1, fclose(fp));
+
+ // Buffered case where we won't notice until the fclose(3).
+ // It's likely this is what was actually seen in http://b/7229520,
+ // and that expecting fprintf to fail is setting yourself up for
+ // disappointment. Remember to check fclose(3)'s return value, kids!
+ ASSERT_NE(nullptr, fp = tmpfile());
+ ASSERT_EQ(4, fprintf(fp, "epic"));
+ ASSERT_EQ(0, close(fileno(fp)));
+ ASSERT_EQ(4, fprintf(fp, "fail"));
+ ASSERT_EQ(-1, fclose(fp));
+}
+
TEST(stdio, popen) {
FILE* fp = popen("cat /proc/version", "r");
ASSERT_TRUE(fp != NULL);
@@ -560,9 +583,11 @@
ASSERT_STREQ("C.UTF-8", setlocale(LC_CTYPE, "C.UTF-8"));
uselocale(LC_GLOBAL_LOCALE);
- // For glibc we need to close and re-open the file in order for fseek to work
- // after using setlocale(LC_CTYPE, "C.UTF-8") and fputwc.
- // TODO: find out if this is expected or a bug in glibc.
+ // In glibc-2.16 fseek doesn't work properly in wide mode
+ // (https://sourceware.org/bugzilla/show_bug.cgi?id=14543). One workaround is
+ // to close and re-open the file. We do it in order to make the test pass
+ // with all glibcs.
+
TemporaryFile tf;
FILE* fp = fdopen(tf.fd, "w+");
ASSERT_TRUE(fp != NULL);