Merge "Enable native_bridge_support"
diff --git a/libc/bionic/malloc_heapprofd.cpp b/libc/bionic/malloc_heapprofd.cpp
index 2aeb9bf..5d3735d 100644
--- a/libc/bionic/malloc_heapprofd.cpp
+++ b/libc/bionic/malloc_heapprofd.cpp
@@ -143,22 +143,23 @@
}
}
+constexpr char kHeapprofdProgramPropertyPrefix[] = "heapprofd.enable.";
+constexpr size_t kHeapprofdProgramPropertyPrefixSize = sizeof(kHeapprofdProgramPropertyPrefix) - 1;
+constexpr size_t kMaxCmdlineSize = 512;
+
static bool GetHeapprofdProgramProperty(char* data, size_t size) {
- constexpr char prefix[] = "heapprofd.enable.";
- // - 1 to skip nullbyte, which we will write later.
- constexpr size_t prefix_size = sizeof(prefix) - 1;
- if (size < prefix_size) {
+ if (size < kHeapprofdProgramPropertyPrefixSize) {
error_log("%s: Overflow constructing heapprofd property", getprogname());
return false;
}
- memcpy(data, prefix, prefix_size);
+ memcpy(data, kHeapprofdProgramPropertyPrefix, kHeapprofdProgramPropertyPrefixSize);
int fd = open("/proc/self/cmdline", O_RDONLY | O_CLOEXEC);
if (fd == -1) {
error_log("%s: Failed to open /proc/self/cmdline", getprogname());
return false;
}
- char cmdline[128];
+ char cmdline[kMaxCmdlineSize];
ssize_t rd = read(fd, cmdline, sizeof(cmdline) - 1);
close(fd);
if (rd == -1) {
@@ -167,7 +168,7 @@
}
cmdline[rd] = '\0';
char* first_arg = static_cast<char*>(memchr(cmdline, '\0', rd));
- if (first_arg == nullptr || first_arg == cmdline + size - 1) {
+ if (first_arg == nullptr) {
error_log("%s: Overflow reading cmdline", getprogname());
return false;
}
@@ -192,12 +193,12 @@
}
size_t name_size = static_cast<size_t>(first_arg - start);
- if (name_size >= size - prefix_size) {
+ if (name_size >= size - kHeapprofdProgramPropertyPrefixSize) {
error_log("%s: overflow constructing heapprofd property.", getprogname());
return false;
}
// + 1 to also copy the trailing null byte.
- memcpy(data + prefix_size, start, name_size + 1);
+ memcpy(data + kHeapprofdProgramPropertyPrefixSize, start, name_size + 1);
return true;
}
@@ -213,7 +214,7 @@
return true;
}
- char program_property[128];
+ char program_property[kHeapprofdProgramPropertyPrefixSize + kMaxCmdlineSize];
if (!GetHeapprofdProgramProperty(program_property,
sizeof(program_property))) {
return false;
diff --git a/libc/stdio/local.h b/libc/stdio/local.h
index d306a21..1ecf122 100644
--- a/libc/stdio/local.h
+++ b/libc/stdio/local.h
@@ -204,6 +204,7 @@
__LIBC32_LEGACY_PUBLIC__ int _fwalk(int (*)(FILE*));
off64_t __sseek64(void*, off64_t, int);
+int __sflush_locked(FILE*);
int __swhatbuf(FILE*, size_t*, int*);
wint_t __fgetwc_unlock(FILE*);
wint_t __ungetwc(wint_t, FILE*);
diff --git a/libc/stdio/refill.c b/libc/stdio/refill.c
index cfa2bfd..1df4191 100644
--- a/libc/stdio/refill.c
+++ b/libc/stdio/refill.c
@@ -40,7 +40,7 @@
lflush(FILE *fp)
{
if ((fp->_flags & (__SLBF|__SWR)) == (__SLBF|__SWR))
- return (__sflush(fp)); /* ignored... */
+ return (__sflush_locked(fp)); /* ignored... */
return (0);
}
diff --git a/libc/stdio/stdio.cpp b/libc/stdio/stdio.cpp
index 4cec757..91c7689 100644
--- a/libc/stdio/stdio.cpp
+++ b/libc/stdio/stdio.cpp
@@ -106,7 +106,7 @@
FILE* stdout = &__sF[1];
FILE* stderr = &__sF[2];
-static pthread_mutex_t __stdio_mutex = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP;
+static pthread_mutex_t __stdio_mutex = PTHREAD_MUTEX_INITIALIZER;
static uint64_t __get_file_tag(FILE* fp) {
// Don't use a tag for the standard streams.
@@ -211,21 +211,23 @@
}
int _fwalk(int (*callback)(FILE*)) {
- pthread_mutex_lock(&__stdio_mutex);
int result = 0;
for (glue* g = &__sglue; g != nullptr; g = g->next) {
FILE* fp = g->iobs;
for (int n = g->niobs; --n >= 0; ++fp) {
- ScopedFileLock sfl(fp);
if (fp->_flags != 0 && (fp->_flags & __SIGN) == 0) {
result |= (*callback)(fp);
}
}
}
- pthread_mutex_unlock(&__stdio_mutex);
return result;
}
+extern "C" __LIBC_HIDDEN__ void __libc_stdio_cleanup(void) {
+ // Equivalent to fflush(nullptr), but without all the locking since we're shutting down anyway.
+ _fwalk(__sflush);
+}
+
static FILE* __fopen(int fd, int flags) {
#if !defined(__LP64__)
if (fd > SHRT_MAX) {
@@ -520,6 +522,11 @@
return 0;
}
+int __sflush_locked(FILE* fp) {
+ ScopedFileLock sfl(fp);
+ return __sflush(fp);
+}
+
int __sread(void* cookie, char* buf, int n) {
FILE* fp = reinterpret_cast<FILE*>(cookie);
return TEMP_FAILURE_RETRY(read(fp->_file, buf, n));
@@ -1061,7 +1068,7 @@
}
static int fflush_all() {
- return _fwalk(__sflush);
+ return _fwalk(__sflush_locked);
}
int fflush(FILE* fp) {
diff --git a/libc/stdlib/atexit.c b/libc/stdlib/atexit.c
index 692e0c0..0efb118 100644
--- a/libc/stdlib/atexit.c
+++ b/libc/stdlib/atexit.c
@@ -188,7 +188,8 @@
/* If called via exit(), flush output of all open files. */
if (dso == NULL) {
- fflush(NULL);
+ extern void __libc_stdio_cleanup(void);
+ __libc_stdio_cleanup();
}
/* BEGIN android-changed: call __unregister_atfork if dso is not null */
diff --git a/libdl/Android.bp b/libdl/Android.bp
index cf723be..e36ddc5 100644
--- a/libdl/Android.bp
+++ b/libdl/Android.bp
@@ -49,6 +49,7 @@
ldflags: [
"-Wl,--exclude-libs=libgcc.a",
+ "-Wl,--exclude-libs=libgcc_stripped.a",
"-Wl,--exclude-libs=libclang_rt.builtins-arm-android.a",
"-Wl,--exclude-libs=libclang_rt.builtins-aarch64-android.a",
"-Wl,--exclude-libs=libclang_rt.builtins-x86-android.a",
@@ -130,6 +131,7 @@
ldflags: [
"-Wl,--exclude-libs=libgcc.a",
+ "-Wl,--exclude-libs=libgcc_stripped.a",
"-Wl,--exclude-libs=libclang_rt.builtins-arm-android.a",
"-Wl,--exclude-libs=libclang_rt.builtins-aarch64-android.a",
"-Wl,--exclude-libs=libclang_rt.builtins-x86-android.a",
diff --git a/linker/Android.bp b/linker/Android.bp
index 22055f6..23ef5ac 100644
--- a/linker/Android.bp
+++ b/linker/Android.bp
@@ -319,6 +319,7 @@
ldflags: [
"-Wl,--exclude-libs=libgcc.a",
+ "-Wl,--exclude-libs=libgcc_stripped.a",
"-Wl,--exclude-libs=libclang_rt.builtins-arm-android.a",
"-Wl,--exclude-libs=libclang_rt.builtins-aarch64-android.a",
"-Wl,--exclude-libs=libclang_rt.builtins-x86-android.a",
diff --git a/linker/linker.cpp b/linker/linker.cpp
index b59df73..0de17f7 100644
--- a/linker/linker.cpp
+++ b/linker/linker.cpp
@@ -1039,7 +1039,7 @@
ZipEntry entry;
- if (FindEntry(handle, ZipString(file_path), &entry) != 0) {
+ if (FindEntry(handle, file_path, &entry) != 0) {
// Entry was not found.
close(fd);
return -1;
diff --git a/tests/dlext_test.cpp b/tests/dlext_test.cpp
index eed84a4..67ebf37 100644
--- a/tests/dlext_test.cpp
+++ b/tests/dlext_test.cpp
@@ -134,10 +134,7 @@
ZipArchiveHandle handle;
ASSERT_EQ(0, OpenArchive(lib_path.c_str(), &handle));
ZipEntry zip_entry;
- ZipString zip_name;
- zip_name.name = reinterpret_cast<const uint8_t*>(kLibZipSimpleZip);
- zip_name.name_length = strlen(kLibZipSimpleZip);
- ASSERT_EQ(0, FindEntry(handle, zip_name, &zip_entry));
+ ASSERT_EQ(0, FindEntry(handle, kLibZipSimpleZip, &zip_entry));
extinfo.library_fd_offset = zip_entry.offset;
CloseArchive(handle);
diff --git a/tests/stdio_test.cpp b/tests/stdio_test.cpp
index 65a942c..c237d6d 100644
--- a/tests/stdio_test.cpp
+++ b/tests/stdio_test.cpp
@@ -29,6 +29,7 @@
#include <locale.h>
#include <string>
+#include <thread>
#include <vector>
#include <android-base/file.h>
@@ -2577,3 +2578,24 @@
ASSERT_LT(0, length);
ASSERT_EQ("/proc/self/fd/2", std::string(path, length));
}
+
+TEST(STDIO_TEST, fread_with_locked_file) {
+ // Reading an unbuffered/line-buffered file from one thread shouldn't block on
+ // files locked on other threads, even if it flushes some line-buffered files.
+ FILE* fp1 = fopen("/dev/zero", "r");
+ ASSERT_TRUE(fp1 != nullptr);
+ flockfile(fp1);
+
+ std::thread([] {
+ for (int mode : { _IONBF, _IOLBF }) {
+ FILE* fp2 = fopen("/dev/zero", "r");
+ ASSERT_TRUE(fp2 != nullptr);
+ setvbuf(fp2, nullptr, mode, 0);
+ ASSERT_EQ('\0', fgetc(fp2));
+ fclose(fp2);
+ }
+ }).join();
+
+ funlockfile(fp1);
+ fclose(fp1);
+}