I have an Android native Server app compiled as Platform privileged module that forks itself. This module also uses Android services, like SurfaceFlinger. I need to fork to have one sandboxed process per client.
Fork() works fine and the parent process has no issue at all. But in the child process, when I try to access any Android service/resource I get:
signal 11 (SIGSEGV), code 2 (SEGV_ACCERR), fault addr xxxxxxxx ... ...
/system/lib/libbinder.so (android::Parcel::ipcSetDataReference
...
/system/lib/libbinder.so (android::BpBinder::transact
NativeCrashListener( 1203): Couldn't find ProcessRecord for pid XXXX
This happens even when I try to create a NEW client, thus, not using any previous created reference.
NativeCrashListener doesn't know about my child process, thus, maybe ActivityManager also doesn't.
I looked at the Zygote code but have not found anything helpful there. I'm probably missing some step or calling some function on the child process. Any ideas ??? =)
You can't create a new Binder process this way.
The problem is that fork() only clones the current thread, not all threads. In the new process, the Binder IPC code will expect the Binder helper threads to be running, but none of them will be. You need to fork() and then exec().
The zygote process avoids this issue by having only one thread running when fork() is called. It deliberately defers initialization of the Binder code to the child process. (In the current implementation, it actually has a couple of threads running in Dalvik, but the internal fork handling stops and restarts those threads on every fork).
fadden is right, fork() cannot be used to create a new process that uses Android APIs reliably. The best you can do with it is exec() to run a standalone command-line program, everything else is likely to not work as you expect.
However, the platform supports sandboxed processes, in the form of isolated service processes. See http://developer.android.com/guide/topics/manifest/service-element.html#isolated for more details. In essence, this runs your service in a special process under a random UID that has no permissions.
For the record, this is what Chrome on Android uses to isolate 'tabs' into sandboxed 'renderer processes'.
Related
I would like to debug a system framework running on an Android device.
In particular, GpsLocationProvider sometimes stops for a while, and I would like to know what it is doing. I found the class contains a android.os.Handler that gets messages posted to it, to communicate between threads. Sometimes it takes minutes between a message is sent, and Handler.handleMessage is called. I interpret that the thread belonging to the Handler's Looper is busy.
I would like to attach a debugger, pause that thread, and see what's currently executing. Alternatively, somehow get a traceback of that thread. Is there any way to do that?
I tried creating an Android Studio project from the source tree with development/tools/idegen/idegen.sh, but I'm not sure how to proceed from there. In case it matters, the (legacy) device is running Android 6.
I've also just discovered debuggerd. I call logcat -s GpsLocationProvider to find the corresponding PID, and feed it to debuggerd, both with and without -b argument. However, this only gives be a backtrace into native code. I don't see any java code there.
If I'm not mistaken, if you have the respective Android API version in your AndroidStudio (installed through SDK Manager), you can install debug variant of your app on the device and then put breakpoints inside Android's code.
This way you can pause the execution of the component's code and see what it's doing.
Context
I am developing an Android app that embeds a Python interpreter. I use JNI to execute C code and the C-Python API to run Python code and also to make Android functionality available in Python via extensions. The Python interpreter needs to:
run in its own process
be able to call itself to start another (many) Python interpreter(s), each in its own process (via Python extension)
be able to call back into Java and do Android things, e.g. request a System Service to use device sensors (via Python extension)
Here is a diagram of my current implementation.
It works pretty well as long as I am in the same process. When I try to fork it gets messy.
Approach 1 - fork in C using fork()
The app starts a background Service (in the app’s process). The Service calls a native method where I use the fork() system call. The child process inits Python and the Python extensions. The extensions are used to start new Python interpreters; and call into Java code (via JNI) to e.g. use System Services.
Forking repeatedly (recursively), running Python code, using C-Python extensions and calling back into Java works.
What does not work is using the Android Application Context from the parent process to use System Services, which leads to segmentation faults. Something that is probably not surprising when one forks and still wants to use stuff from the parent’s address space.
Btw. I get the context from a static function in an Application subclass, where I store it when the app first gets started, which I know is discouraged.
Approach 2 - Let Android fork using android:process
I let Android fork my background Service by adding android:process to the service definition in AndroidManifest.xml. Then I call a native method that inits Python and the extensions. Now, when I use my extensions to call into Java and use System Services I don’t get segmentation faults. Probably because Android has created a new Virtual Machine, with a fresh context and I don’t have to access anything from the parent process’ address space (especially now that the parent of my new process is Zygote and not my original App process).
The problem with this approach is that I can’t start multiple instances of a Service/Process to have multiple Python interpreters.
TL;DR
When I fork a process in an Android native method, how can I avoid segmentation faults when I try to call System Services in that child process?
Is there a way to have my App create new processes (ideally with a new Virtual Machine), without specifying them in the AndroidManifest.xml
Resources (I don't have enough reputations to post the links)
Android Guide - Process and Threads (This somehow tells me, this is do-able, but not how)
Kivy Python for Android (Interpreter does not fork)
Script Layer for Android (Interpreter forks but does not use JNI to call into Java)
Java ProcessBuilder (Forks a new process to execv a native program, which can’t call into Java)
I am implementing one library for Applications. Traceview after application is using the library looks like :
If I am not using the library, Only main thread is shown in the traceview. So what are these different Daemons,JDWP and Binders and when these are started by Android OS ?
FinalizerDaemon is used to abort if any finaliser is running longer.
FinalizerWatchdog is watch dog service for finaliser daemon.
JDWP is java debugger service.
ReferenceQueueDaemon is heap management thread moves elements from the garbage collector's pending list to the managed reference queue.
Not sure about binders.
More details at https://android.googlesource.com/platform/libcore/+/a7752f4d22097346dd7849b92b9f36d0a0a7a8f3/libdvm/src/main/java/java/lang/Daemons.java
I'm using DDMS to monitor threads in my app, and I see that my app has a bunch of native threads as shown in follow picture. And time to time, the number of native threads increased as user interact with my app, which cause my app sometime does not serve as I expect. Is there anyway to kill these native threads?
There is no such thing as a "native thread" on Android, although some people might use that to refer to threads that are not attached to the VM (which would also make them invisible to DDMS). The threads happen to be executing (or waiting) in native code at the time you did a thread dump, but may spend most of their time executing bytecode. (A list of Dalvik thread states is available here.)
The names of the threads suggests that they were created without being given an explicit name. The one thread with a name, NsdManager probably exists because you're using NsdManager, which "responses to requests from an application are on listener callbacks on a seperate thread" [sic].
It's possible that you can glean some useful information from a stack trace. In DDMS, double-click the thread to get a backtrace. On a rooted device, you can kill -3 <pid> to get a full dump, including native stack frames.
Killing arbitrary threads is not allowed, as they might be holding locks or other resources. If you can determine what is starting them, and that they are unnecessary, you can prevent them from being started in the first place.
I am trying to understand how Android launches applications. The question is how (and why) does the Zygote fork a new Dalvik VM? I do not understand why it is not possible to run multiple applications in the same Dalvik VM.
Q. how does zygote exactly fork Dalvik VM?
Short Answer:
The Zygote process cold boots a Java VM on system start up. It then listens to a socket for incoming commands. Other processes (e.g. ActivityManagerService) write commands to this socket whenever a new process is needed for an application. These commands are read by the Zygote process which calls fork() as necessary. Child processes get a pre-warmed VM in which to run. This is how Zygote forks the Dalvik VM.
Long answer: After the kernel is loaded, init.rc is parsed and native services are started. Then /system/bin/app_process) is run. This eventually calls AndroidRuntime.start(), passing it the parameters com.android.internal.os.ZygoteInit and start-system-server.
The AndroidRuntime.start() starts a Java VM then calls ZygoteInit.main(), passing it the parameter start-system-server.
ZygoteInit.main() registers the Zygote socket (which the Zygote process listens to for incoming commands, and on receiving new command, spawns a new process as requested). It then preloads a lot of classes (as listed in frameworks/base/preloaded-classes, over 4500 in Android 8.0) and all the system-wide resources like drawables, xmls, etc. Then it calls startSystemServer() which forks a new process for com.android.server.SystemServer. This fork is special and is not done in the same manner as the usual forks the Zygote performs on behalf of requesting processes.
After SystemServer is forked the runSelectLoopMode() function is called. This is a while(true) loop which establishes a ZygoteConnection with the Zygote socket and waits for commands on it. When a command is received, ZygoteConnection.runOnce() is called.
ZygoteConnection.runOnce() then calls Zygote.forkAndSpecialize() which then calls a native function to do the actual fork. Thus, like in the case of SystemServer, a child process is created which inherits a pre-warmed Dalvik VM for itself.
Q. why it is not possible to run multiple applications in the same
Dalvik VM?
This is a design decision as far as I know. The Android guys just decided to fork a new VM per process for security via sandboxing.
No. Dalvik doesn't span processes.
However, the Binder IPC mechanism can do a very convincing job of making objects appear to migrate to a different process and its Dalvik instance. Also, the memory management is very good about sharing read-only pages across all processes that need them. The Dalvik process hosting a typical app is forked off of zygote with all the common android libraries already mapped, so new unique copies don't have to be opened.
Source: Do apps using multiple processes share a Dalvik instance?
Also check these links:
http://davidehringer.com/software/android/The_Dalvik_Virtual_Machine.pdf
http://commonsware.com/blog/Articles/what-is-dalvik.html
Zygote is also used to share the system drawables with all the apps.
This allows the system to load the bitmaps for buttons only once for
instance.
Just to add one more point to answers above when zygote does a fork on receiving a command it uses copy-on-write technique. Memory is copied only when the new process tries to modify it.
Also the core libraries that zygote loads on startup are read only and cannot be modified. So they are not copied over but shared with new forked processes.
All of these led to quick startup and less memory footprint.
Zygote isn't really bound up with Dalvik, it's just an init process. Zygote is the method Android uses to start apps. Rather than having to start each new process from scratch, loading the whole system and the Android framework afresh each time you want to start an app, it does that process once, and then stops at that point, before Zygote has done anything app-specific. Then, when you want to start an app, the Zygote process forks, and the child process continues where it left off, loading the app itself into the VM.