File descriptor disappearing

95 views
Skip to first unread message

Bryan Ashby

unread,
Nov 16, 2010, 3:56:16 PM11/16/10
to android-ndk
I have a very strange issue I'm having trouble tracking down:

I have compiled my own version of sqlite3 using with encryption
support that I've been using in native code. This has been working
fine. However, a strange issue has started occuring: The underlying
file descriptor used by the sqlite3.c code is being mysteriously
closed/disappearing causing fcntl()'s for F_SETLK for example to fail
with errno of EBADF (9).

In debugging this, I am not calling sqlite3_close(). The code path I
can go through many times then all of a sudden the descriptor is
invalid (/proc/PID/fd/DESC is no longer present).

Any ideas? It's almost as if Android is cleaning up the handle...
though I'm still using it! It's created entirely in native code, so I
don't think the VM should be touching it somehow.

Bryan Ashby

unread,
Nov 16, 2010, 4:52:22 PM11/16/10
to android-ndk
As a update to this, the file descriptor is present in /proc/PID/fd &
everything is working, then I see a "GC_FOR_MALLOC freed..." in
logcat, and *poof* it's gone. The file descriptor in question is only
touched by native C code. How would Java know about it and free it?

Bryan Ashby

unread,
Nov 16, 2010, 6:21:50 PM11/16/10
to android-ndk
Yet another update:

It appears if that if I move the sqlite-touching code to a different
thread (anything other than the main Java thread), the file descriptor
is never cleared.

Is this a bug? Why is a descriptor (opened via Posix open() ) cleaned
up by the JVM when it's something not referenced by Java/JNI at all?

Bryan Ashby

unread,
Nov 19, 2010, 3:59:52 PM11/19/10
to android-ndk
Sorry for the 'bump'. Has anyone seen this issue before? It really
appears as if the JVM is cleaning up _file descriptors_ that were
created by native open()'s.

If I'm not doing something crazy, I'll file a bug.

Dianne Hackborn

unread,
Nov 19, 2010, 4:28:18 PM11/19/10
to andro...@googlegroups.com
I doubt Dalvik is closing a file descriptor that hasn't been given to it, though of course most anything is possible.  If you do file a bug, please include a small as possible reproducible case; this isn't an issue that I have ever heard of for, so I don't think there is much anyone can do without a good way to repro.


--
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.

fadden

unread,
Nov 22, 2010, 12:43:15 PM11/22/10
to android-ndk
The only way this would make sense is if somebody stuffed the fd into
an object that closes its descriptor.

You can try setting a breakpoint on close() and see if you can catch
somebody in the act. This gets a bit tedious in a busy process
though. If you're building your own copy of the platform you can
instrument bionic's close() call (wrap the syscall in something that
tests against a global variable with the "special" fd in it and freaks
out if somebody closes it).

Another thought would be to dup2() the descriptor to a high value
(like 999) immediately after opening it. That would help rule out
somebody calling close() on a stale fd value (i.e. there's two objects
that know about fd N and they both call close(), but between the two
calls the sqlite code opens an fd with the same number). If it's
still getting closed, it's likely that somebody is closing it
deliberately.

Bryan Ashby

unread,
Nov 22, 2010, 4:22:04 PM11/22/10
to android-ndk
I created a myProxyClose() function in sqlite3.c that proxies all
close() calls and prints their descriptors to logcat. I then set a
breakpoint where I open the .db file and where sqlite always fails in
unixLock(). When I first start up my program, the .db file is opened.
The descriptor is present in /proc/PID/fd. I then wait a bit until the
failing breakpoint is set. SQLite's internal structs are still
populated as if it has never attempted to close the file, no close for
the particular FD are in logcat (there are plenty of others) and it's
now missing from /proc/PID/fd.

It looks like Android may support inotify. I think I may try to set
something up "watching" the FD.

Jeffrey Brown

unread,
Nov 22, 2010, 11:33:02 PM11/22/10
to andro...@googlegroups.com

You can also try using strace.

Silly question: Are you sure the file descriptor was successfully opened in the first place?

Bryan Ashby

unread,
Nov 23, 2010, 5:54:36 PM11/23/10
to android-ndk
Using strace I do see a explicit close() call to the file descriptor
in question. SQLite's close calls have not been called, however (it
still thinks it's open). Yes, the file descriptor was good and sqlite
has been using it (I can read/write the DB until it gets closed).

I can't seem to get any useful backtrace for close(), unfortunately: I
set a breakpoint for close() with the condition of
$r0=<file_descriptor>. When it's hit, bt only displays the following:
#1 0xad345922 in ?? ()


On Nov 22, 9:33 pm, Jeffrey Brown <jeffbr...@android.com> wrote:
> You can also try using strace.
>
> Silly question: Are you sure the file descriptor was successfully opened in
> the first place?
> android-ndk...@googlegroups.com<android-ndk%2Bunsubscribe@googlegr oups.com>
> .> For more options, visit this group at
>
> http://groups.google.com/group/android-ndk?hl=en.
>
>
>
>
>
>
>
>

fadden

unread,
Nov 23, 2010, 7:49:51 PM11/23/10
to android-ndk
On Nov 23, 2:54 pm, Bryan Ashby <nuskoo...@gmail.com> wrote:
> Using strace I do see a explicit close() call to the file descriptor
> in question. SQLite's close calls have not been called, however (it
> still thinks it's open). Yes, the file descriptor was good and sqlite
> has been using it (I can read/write the DB until it gets closed).

Try the dup2() trick to see if it's deliberate.

Freepine

unread,
Nov 23, 2010, 8:23:39 PM11/23/10
to andro...@googlegroups.com
For stock Android, libandroid_runtime.so is prelinked to 0xad300000.
So perhaps you can add the symbol file of libandroid_runtime.so in gdb and try bt again.

To unsubscribe from this group, send email to android-ndk...@googlegroups.com.

Bryan Ashby

unread,
Nov 23, 2010, 10:08:42 PM11/23/10
to android-ndk
I had made a quick pass with your suggestion previously, but it
occurred to me I screwed it up. I tried it again just now. Here is
what happens:

original open() gives fd 29
dup2() fd as 999
/proc/PID/fd shows both 29 and 999 as proper .db file
(time passes)
/proc/PID/fd now shows only 999 with the proper db file; 29 is now
pointing to /dev/ashmem

...huh?!

Any clues?

Bryan Ashby

unread,
Nov 29, 2010, 1:31:27 PM11/29/10
to android-ndk
Was able to try this today. It now spits out the following:

#0 0xafd0d980 in close ()
from /cygdrive/c/dev/ghoti/client/Daemon/nix/android/CPDaemon/obj/
local/armeabi/libc.so
#1 0xad345922 in ?? ()
from /cygdrive/c/dev/ghoti/client/Daemon/nix/android/CPDaemon/obj/
local/armeabi/libandroid_runtime.so


Not very helpful. Not sure why it's not giving any real information?!

Any other ideas? If I could get some debug information this would be
easy!

Chris Stratton

unread,
Nov 29, 2010, 2:22:26 PM11/29/10
to android-ndk
I would adb pull the .so off the phone, use the ndk's objdump on it,
which will probably get you (mangled) function names, and manually
compare
those against the sources (recursive grep is useful) to figure out
what you
are looking at around the subject address.
Reply all
Reply to author
Forward
0 new messages