blob: 717803dd9f9cacec576bbc5b2184815bc9c7bba9 [file] [log] [blame]
/*
* Copyright (C) 2008 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.
*/
/*
* dalvik.system.Zygote
*/
#include "Dalvik.h"
#include "Thread.h"
#include "native/InternalNativePriv.h"
#include <sys/resource.h>
#if defined(HAVE_PRCTL)
# include <sys/prctl.h>
#endif
#define ZYGOTE_LOG_TAG "Zygote"
/* must match values in com.android.internal.os.Zygote */
enum {
DEBUG_ENABLE_DEBUGGER = 1,
DEBUG_ENABLE_CHECKJNI = 1 << 1,
DEBUG_ENABLE_ASSERT = 1 << 2,
DEBUG_ENABLE_SAFEMODE = 1 << 3,
DEBUG_ENABLE_JNI_LOGGING = 1 << 4,
};
/*
* Enable/disable debug features requested by the caller.
*
* debugger
* If set, enable debugging; if not set, disable debugging. This is
* easy to handle, because the JDWP thread isn't started until we call
* dvmInitAfterZygote().
* checkjni
* If set, make sure "check JNI" is enabled.
* assert
* If set, make sure assertions are enabled. This gets fairly weird,
* because it affects the result of a method called by class initializers,
* and hence can't affect pre-loaded/initialized classes.
* safemode
* If set, operates the VM in the safe mode. The definition of "safe mode" is
* implementation dependent and currently only the JIT compiler is disabled.
* This is easy to handle because the compiler thread and associated resources
* are not requested until we call dvmInitAfterZygote().
*/
static void enableDebugFeatures(u4 debugFlags)
{
gDvm.jdwpAllowed = ((debugFlags & DEBUG_ENABLE_DEBUGGER) != 0);
if ((debugFlags & DEBUG_ENABLE_CHECKJNI) != 0) {
/* turn it on if it's not already enabled */
dvmLateEnableCheckedJni();
}
if ((debugFlags & DEBUG_ENABLE_JNI_LOGGING) != 0) {
gDvmJni.logThirdPartyJni = true;
}
if ((debugFlags & DEBUG_ENABLE_ASSERT) != 0) {
/* turn it on if it's not already enabled */
dvmLateEnableAssertions();
}
if ((debugFlags & DEBUG_ENABLE_SAFEMODE) != 0) {
#if defined(WITH_JIT)
/* turn off the jit if it is explicitly requested by the app */
if (gDvm.executionMode == kExecutionModeJit)
gDvm.executionMode = kExecutionModeInterpFast;
#endif
}
#ifdef HAVE_ANDROID_OS
if ((debugFlags & DEBUG_ENABLE_DEBUGGER) != 0) {
/* To let a non-privileged gdbserver attach to this
* process, we must set its dumpable bit flag. However
* we are not interested in generating a coredump in
* case of a crash, so also set the coredump size to 0
* to disable that
*/
if (prctl(PR_SET_DUMPABLE, 1, 0, 0, 0) < 0) {
ALOGE("could not set dumpable bit flag for pid %d: %s",
getpid(), strerror(errno));
} else {
struct rlimit rl;
rl.rlim_cur = 0;
rl.rlim_max = RLIM_INFINITY;
if (setrlimit(RLIMIT_CORE, &rl) < 0) {
ALOGE("could not disable core file generation for pid %d: %s",
getpid(), strerror(errno));
}
}
}
#endif
}
/*
* native public static long nativePreFork()
*/
static void Dalvik_dalvik_system_ZygoteHooks_preFork(const u4* args,
JValue* pResult)
{
dvmDumpLoaderStats("zygote");
if (!gDvm.zygote) {
dvmThrowIllegalStateException(
"VM instance not started with -Xzygote");
RETURN_LONG(-1L);
}
if (!dvmGcPreZygoteFork()) {
ALOGE("pre-fork heap failed");
dvmAbort();
}
RETURN_LONG(0L);
}
/*
* native public static int nativePostForkChild(long token, int debug_flags),
*/
static void Dalvik_dalvik_system_ZygoteHooks_postForkChild(
const u4* args, JValue* pResult)
{
/*
* Our system thread ID has changed. Get the new one.
*/
Thread* thread = dvmThreadSelf();
thread->systemTid = dvmGetSysThreadId();
/* configure additional debug options */
enableDebugFeatures(args[2]);
gDvm.zygote = false;
if (!dvmInitAfterZygote()) {
ALOGE("error in post-zygote initialization");
dvmAbort();
}
RETURN_VOID();
}
const DalvikNativeMethod dvm_dalvik_system_ZygoteHooks[] = {
{ "nativePreFork", "()J",
Dalvik_dalvik_system_ZygoteHooks_preFork },
{ "nativePostForkChild", "(JI)V",
Dalvik_dalvik_system_ZygoteHooks_postForkChild },
{ NULL, NULL, NULL },
};