Bug 1545007 - Remove our pthread_atfork implementation for Android. r=froydnj

Bug 884239 added a build-time Android version check around the
pthread_atfork function definition at the same time as for timer_create,
which was subsequently removed. But it turns out the version that
documented was wrong: per the comment added in bug 680190,
pthread_atfork might have been supported since Android 2.3 (gingerbread,
API 9 or 10). That might not be entirely accurate, though, because the
bionic repository seems to show it made it to Android 4.0 (ice cream
sandwich, API 14 or 15).

Either way, that is less than the minimum API version we currently
support, which is 16.

Differential Revision: https://phabricator.services.mozilla.com/D27848

--HG--
extra : moz-landing-system : lando
This commit is contained in:
Mike Hommey 2019-04-17 18:26:02 +00:00
Родитель feb0789249
Коммит 777665d869
1 изменённых файлов: 1 добавлений и 90 удалений

Просмотреть файл

@ -3,101 +3,12 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
#include <pthread.h>
#include <string.h>
#include <stdlib.h>
#include <time.h>
#include <sys/types.h>
#include <unistd.h>
#include <android/log.h>
#include <sys/syscall.h>
#include "mozilla/Alignment.h"
#include <vector>
#define NS_EXPORT __attribute__((visibility("default")))
#if ANDROID_VERSION < 17 || defined(MOZ_WIDGET_ANDROID)
/* Android doesn't have pthread_atfork(), so we need to use our own. */
struct AtForkFuncs {
void (*prepare)(void);
void (*parent)(void);
void (*child)(void);
};
/* jemalloc's initialization calls pthread_atfork. When pthread_atfork (see
* further below) stores the corresponding data, it's going to allocate memory,
* which will loop back to jemalloc's initialization, leading to a dead-lock.
* So, for that specific vector, we use a special allocator that returns a
* static buffer for small sizes, and force the initial vector capacity to
* a size enough to store one atfork function table. */
template <typename T>
struct SpecialAllocator : public std::allocator<T> {
SpecialAllocator() : bufUsed(false) {}
inline typename std::allocator<T>::pointer allocate(
typename std::allocator<T>::size_type n, const void * = 0) {
if (!bufUsed && n == 1) {
bufUsed = true;
return buf.addr();
}
return reinterpret_cast<T *>(::operator new(sizeof(T) * n));
}
inline void deallocate(typename std::allocator<T>::pointer p,
typename std::allocator<T>::size_type n) {
if (p == buf.addr())
bufUsed = false;
else
::operator delete(p);
}
template <typename U>
struct rebind {
typedef SpecialAllocator<U> other;
};
private:
mozilla::AlignedStorage2<T> buf;
bool bufUsed;
};
static std::vector<AtForkFuncs, SpecialAllocator<AtForkFuncs> > atfork;
#endif
#if ANDROID_VERSION < 17 || defined(MOZ_WIDGET_ANDROID)
extern "C" NS_EXPORT int pthread_atfork(void (*prepare)(void),
void (*parent)(void),
void (*child)(void)) {
AtForkFuncs funcs;
funcs.prepare = prepare;
funcs.parent = parent;
funcs.child = child;
if (!atfork.capacity()) atfork.reserve(1);
atfork.push_back(funcs);
return 0;
}
extern "C" NS_EXPORT pid_t __fork(void);
extern "C" NS_EXPORT pid_t fork(void) {
pid_t pid;
for (auto it = atfork.rbegin(); it < atfork.rend(); ++it)
if (it->prepare) it->prepare();
switch ((pid = syscall(__NR_clone, SIGCHLD, NULL, NULL, NULL, NULL))) {
case 0:
for (auto it = atfork.begin(); it < atfork.end(); ++it)
if (it->child) it->child();
break;
default:
for (auto it = atfork.begin(); it < atfork.end(); ++it)
if (it->parent) it->parent();
}
return pid;
}
#endif
extern "C" NS_EXPORT int raise(int sig) {
// Bug 741272: Bionic incorrectly uses kill(), which signals the
// process, and thus could signal another thread (and let this one