SIGILL and fork

468 views
Skip to first unread message

d1m_bu1b

unread,
Aug 17, 2010, 12:35:01 PM8/17/10
to android-ndk
I am writing a portable native level benchmarking tool where one,
amongst many, of the metrics is to measure the number of fork-able
processes. This tool is meant to run on multiple Linux platforms.

When I fork multiple times (200-500-ish) in an android apk the parent
process receives a signal 11 and dies.
I have yet to run this as a non APK shell app.

The child processes simply sleep for a sec then exit.

Does anyone have any insight as to why you can fork a few but not fork
many?

Other Linux distros do not crash the app once the limit is reached.

Thank you for any insight.

Onur Cinar

unread,
Aug 17, 2010, 12:43:08 PM8/17/10
to andro...@googlegroups.com

Hi,

Please make sure that you are not running the benchmarking tasks from the UI thread. If the UI thread gets blocked for a certain amount of time (5 or 10 sec), it will trigger an ANR. So you may want to have a separate thread to run the benchmarking tasks.  Is that the case?

Regards,

-onur



--
You received this message because you are subscribed to the Google Groups "android-ndk" group.
To post to this group, send email to andro...@googlegroups.com.
To unsubscribe from this group, send email to android-ndk...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/android-ndk?hl=en.

---
www.zdo.com

fadden

unread,
Aug 17, 2010, 5:03:46 PM8/17/10
to android-ndk
On Aug 17, 9:35 am, d1m_bu1b <bubba...@gmail.com> wrote:
> When I fork multiple times (200-500-ish) in an android apk the parent
> process receives a signal 11 and dies.
> I have yet to run this as a non APK shell app.

What does the crash look like in logcat?

Nalin Savara

unread,
Aug 17, 2010, 6:04:36 PM8/17/10
to andro...@googlegroups.com
@d1m... A few observations:-

1. fork() etc are c stdlib functions whose usage is undesirable in
android, sure they are there, but they are outside Android's framework
which gracefully manages process suspend and shut...

So, under normal circumstances you should use the sanity checked ways
of doing threads in android.

2. More processes in memory mean more processor cycles used and hence
more battery consumption.
(am no android God... So correct me if i'm wrong below, but this how I
understood Android's architecture to be)
so android had some design decisions/assumptions about limiting max
processes in memory and/or killing or suspending processes once a
threshold is crossed.
As you are using fork which is from c stdlib base layer rather than a
android function, hence Everything runs totally raw and android's
sanity checks/gracefully suspend and exit things will not be available
to your esteemed processes and they will die badly.

This seems to be happening, and you should take it as a lesson to do
things the Android way rather than leave you benchmark app as a
example of wrong/non-android ways of doing things.

hope this helps... Comments and criticisms welcome...

Regards,
Nalin

>> android-ndk...@googlegroups.com<android-ndk%2Bunsu...@googlegroups.com>


>> .
>> For more options, visit this group at
>> http://groups.google.com/group/android-ndk?hl=en.
>>
>> ---
> www.zdo.com
>
> --
> You received this message because you are subscribed to the Google Groups
> "android-ndk" group.
> To post to this group, send email to andro...@googlegroups.com.
> To unsubscribe from this group, send email to
> android-ndk...@googlegroups.com.
> For more options, visit this group at
> http://groups.google.com/group/android-ndk?hl=en.
>
>

--
Sent from my mobile device

David Given

unread,
Aug 18, 2010, 6:49:23 AM8/18/10
to andro...@googlegroups.com
On 17/08/10 23:04, Nalin Savara wrote:
[...]

> 1. fork() etc are c stdlib functions whose usage is undesirable in
> android, sure they are there, but they are outside Android's framework
> which gracefully manages process suspend and shut...

fork and pthreads are not compatible. If you fork a process containing
semaphores, mutexes etc, their state in the new process is *undefined*.
(I ran into this with another program where on some Linux systems it
would work and on other Linux systems it would not work. Turned out that
certain versions of the Linux kernel on certain architectures would
silently unlock any semaphores when the process was forked.)

About the only thing you can do in a pthreads-using application with
fork is to immediately exec afterwards, and even that's problematic (if
another thread opens a file descriptor just before the fork the file
descriptor will end up being propagated to the child process)...

--
┌─── dg@cowlark.com ───── http://www.cowlark.com ─────

│ life←{ ↑1 ⍵∨.^3 4=+/,¯1 0 1∘.⊖¯1 0 1∘.⌽⊂⍵ }
│ --- Conway's Game Of Life, in one line of APL

signature.asc

Nalin Savara

unread,
Aug 18, 2010, 2:11:45 PM8/18/10
to andro...@googlegroups.com
@Dianne Hackborn, David I Turner, Jason:

Is the point (2) I put correct ? That was my understanding based on articles/interviews I read when Android had just been released-- though I am not sure how correct is my understanding about "processes created by fork dying badly when android needs to remove processes".

Would really appreciate a more official clarification on that.


On Wed, Aug 18, 2010 at 3:34 AM, Nalin Savara <nsn...@gmail.com> wrote:
@d1m... A few observations:-

1. fork() etc are c stdlib functions whose usage is undesirable in
android, sure they are there, but they are outside Android's framework
which gracefully manages process suspend and shut...

So, under normal circumstances you should use the sanity checked ways
of doing threads in android.

2. More processes in memory mean more processor cycles used and hence
more battery consumption.
(am no android God... So correct me if i'm wrong below, but this how I
understood Android's architecture to be)
so android had some design decisions/assumptions about limiting max
processes in memory and/or killing or suspending processes once a
threshold is crossed.
As you are using fork which is from c stdlib base layer rather than a
android function, hence Everything runs totally raw and android's
sanity checks/gracefully suspend and exit things will not be available
to your esteemed processes and they will die badly.

This seems to be happening, and you should take it as a lesson to do
things the Android way rather than leave you benchmark app as a
example of wrong/non-android ways of doing things.

Regards,

Nalin

d1m_bu1b

unread,
Aug 18, 2010, 4:51:48 PM8/18/10
to android-ndk
Yes it is and great suggestion thank you.
> > android-ndk...@googlegroups.com<android-ndk%2Bunsu...@googlegroups.com>
> > .

d1m_bu1b

unread,
Aug 18, 2010, 4:52:52 PM8/18/10
to android-ndk
it is not consistent in logcat; but as stated earlier it terminates on
signal 11.

fadden

unread,
Aug 18, 2010, 7:19:43 PM8/18/10
to android-ndk
On Aug 18, 1:52 pm, d1m_bu1b <bubba...@gmail.com> wrote:
> it is not consistent in logcat; but as stated earlier it terminates on
> signal 11.

To get useful stack traces from debuggerd, the libc abort() function
and the Dalvik dvmAbort() function both induce segmentation faults
instead of broadcasting a SIGABRT. So it might be crashing or it
might be aborting. If you can provide additional details from logcat
or your test program we might be able to figure out what's going on.

Dianne Hackborn

unread,
Aug 18, 2010, 7:42:20 PM8/18/10
to andro...@googlegroups.com
Correct.  Please please please do not use fork.  I would like to just completely disable it for app processes, but there are certain geeky situations (such as a app that gives you a shell) where it is useful.  But it should not be considered an API for use in production code.

Fork does not play well with Android.  Do not use. :)

Re fork not working with threads -- this is absolutely true, and since every application process intrinsically has multiple threads you can't avoid the problem.  However, it is not a problem if you use exec() right after the fork, since that resets your process state.  But please don't do that for real code.

--
You received this message because you are subscribed to the Google Groups "android-ndk" group.
To post to this group, send email to andro...@googlegroups.com.
To unsubscribe from this group, send email to android-ndk...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/android-ndk?hl=en.



--
Dianne Hackborn
Android framework engineer
hac...@android.com

Note: please don't send private questions to me, as I don't have time to provide private support, and so won't reply to such e-mails.  All such questions should be posted on public forums, where I and others can see and answer them.

David Given

unread,
Aug 19, 2010, 6:44:33 AM8/19/10
to andro...@googlegroups.com
On 19/08/10 00:42, Dianne Hackborn wrote:
[...]

> However, it is not a problem if you use exec() right after the
> fork, since that resets your process state.

Warning: pedantry follows. (This is not meant as a contradiction, but as
additional information meant to warn people not to do Evil Things.)

exec() doesn't *quite* reset all the process state. It won't close file
descriptors unless they've had FD_CLOEXEC set on them, and the default
is to not set this. This isn't usually a problem, but there's a very
rare and largely inescapable race condition if you're using threads.

Consider this code:

Thread 1:
exec(...)

Thread 2:
fd = open("foo", O_RDONLY);
fcntl(fd, F_SETFD, FD_CLOEXEC);

If thread 1 executes the exec between the open and the fcntl, then the
new file descriptor will get propagated to the new process and really
bad stuff can happen.

This behaviour is actually mandated by Posix and, IMO, is nuts. It means
that the only safe place to call exec() is before you've created any
threads, which isn't really viable in the real world.

Linux has a special extension to open() where if you pass O_CLOEXEC as a
flag, then FD_CLOEXEC will be atomically set on the new file descriptor.
This avoids the race. Unfortunately it's not standard and so nobody does it.

However since nobody on Android should be using either fork() or exec(),
this ought not to be a problem.

signature.asc

fadden

unread,
Aug 19, 2010, 6:57:13 PM8/19/10
to android-ndk
On Aug 19, 3:44 am, David Given <d...@cowlark.com> wrote:
> If thread 1 executes the exec between the open and the fcntl, then the
> new file descriptor will get propagated to the new process and really
> bad stuff can happen.
>
> This behaviour is actually mandated by Posix and, IMO, is nuts. It means
> that the only safe place to call exec() is before you've created any
> threads, which isn't really viable in the real world.

If you're in an environment where you don't have absolute control over
all file descriptors, you still face this problem. For example,
consider the Java Process exec mechanism. Unless the code is in a
position to know about every file descriptor, and guarantee that
they're all close-on-exec, some fds will leak. Since Android allows
arbitrary native code, this guarantee is impossible.

The solution is to fork and then close() every fd in the descriptor
namespace, either via brute-force or by scanning /proc/self/fd.

The fun part is that you have to do this without malloc/free, because
if the parent called fork() while one of its threads was doing a
memory allocation, the child process might think that lock is still
held and any attempt to use malloc() will cause a hang. Since
opendir() uses malloc(), you can't use that to do a directory scan in /
proc/self/fd.
Reply all
Reply to author
Forward
0 new messages