2

I need to port a native library which uses System V shared memory for IPC. There are calls to methods like shmget(), shmctl() & shmdt(). I was able to compile the native code and build the native library, but when I run the library with the help of emulator, the application is crashing.

Below is the line where it's crashing.

iShmId = shmget( tKey, iSize, IPC_CREAT | IPC_EXCL | _DEF_ACCESS );

I'm using Android Studio, Android API level 27.

I came across this link: How to use shared memory in android native code? where it's said that these API's are not supported, but I thought that the latest Android API level 27 might have support for the same.

I verified the ndk-bundle\sysroot\usr\include\sys\shm.h header and these API's are seem to be supported since API 26, below is the extract from shm.h file.

#if __ANDROID_API__ >= 26
void* shmat(int __shm_id, const void* __addr, int __flags) __INTRODUCED_IN(26);
int shmctl(int __shm_id, int __cmd, struct shmid_ds* __buf) __INTRODUCED_IN(26);
int shmdt(const void* __addr) __INTRODUCED_IN(26);
int shmget(key_t __key, size_t __size, int __flags) __INTRODUCED_IN(26);

#endif /* __ANDROID_API__ >= 26 */

Can anyone please let me know what am I missing here. As I'm able to compile & build the library, these API's should be supported. So, I should be missing something.

Below is the error from Logcat:

2018-12-09 12:43:51.313 31453-31473/com.android.phone A/libc: Fatal signal 6 (SIGABRT), code -6 (SI_TKILL) in tid 31473 (HwBinder:31453_), pid 31453 (m.android.phone)
2018-12-09 12:43:51.490 31529-31529/? A/DEBUG: backtrace:
2018-12-09 12:43:51.490 31529-31529/? A/DEBUG:     #00 pc 00000b39  [vdso:e9577000] (__kernel_vsyscall+9)
2018-12-09 12:43:51.490 31529-31529/? A/DEBUG:     #01 pc 0001fdf8  /system/lib/libc.so (syscall+40)
2018-12-09 12:43:51.490 31529-31529/? A/DEBUG:     #02 pc 000321fe  /system/lib/libc.so (shmget+46)
2018-12-09 12:43:51.491 31529-31529/? A/DEBUG:     #03 pc 00016b57  /data/app/com.example.****.app--7DjBy2wqavG-QlF-n6rDg==/lib/x86/libNativeLib.so
2018-12-09 12:43:51.491 31529-31529/? A/DEBUG:     #04 pc 0001684f  /data/app/com.example.****.app--7DjBy2wqavG-QlF-n6rDg==/lib/x86/libNativeLib.so (GetShmSegment+447)
2018-12-09 12:43:51.491 31529-31529/? A/DEBUG:     #05 pc 00014940  /data/app/com.example.****.app--7DjBy2wqavG-QlF-n6rDg==/lib/x86/libNativeLib.so
2018-12-09 12:43:51.491 31529-31529/? A/DEBUG:     #06 pc 000148e7  /data/app/com.example.****.app--7DjBy2wqavG-QlF-n6rDg==/lib/x86/libNativeLib.so (GetCurrentProcessId+23)
2018-12-09 12:43:51.491 31529-31529/? A/DEBUG:     #07 pc 0001b7cf  /data/app/com.example.****.app--7DjBy2wqavG-QlF-n6rDg==/lib/x86/libNativeLib.so (_init+207)
2018-12-09 12:43:51.491 31529-31529/? A/DEBUG:     #08 pc 00023d68  /system/bin/linker (__dl__ZN6soinfo17call_constructorsEv+696)
2018-12-09 12:43:51.492 31529-31529/? A/DEBUG:     #09 pc 00023b6a  /system/bin/linker (__dl__ZN6soinfo17call_constructorsEv+186)
2018-12-09 12:43:51.492 31529-31529/? A/DEBUG:     #10 pc 0000c156  /system/bin/linker (__dl__Z9do_dlopenPKciPK17android_dlextinfoPKv+2102)
2018-12-09 12:43:51.492 31529-31529/? A/DEBUG:     #11 pc 00007263  /system/bin/linker (__loader_android_dlopen_ext+83)
2018-12-09 12:43:51.492 31529-31529/? A/DEBUG:     #12 pc 00000eb6  /system/lib/libdl.so (android_dlopen_ext+38)
2018-12-09 12:43:51.492 31529-31529/? A/DEBUG:     #13 pc 00003998  /system/lib/libnativeloader.so (android::OpenNativeLibrary(_JNIEnv*, int, char const*, _jobject*, _jstring*, bool*, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>>*)+424)
2018-12-09 12:43:51.492 31529-31529/? A/DEBUG:     #14 pc 0031eb61  /system/lib/libart.so (art::JavaVMExt::LoadNativeLibrary(_JNIEnv*, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>> const&, _jobject*, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>>*)+3009)
2018-12-09 12:43:51.492 31529-31529/? A/DEBUG:     #15 pc 000036f6  /system/lib/libopenjdkjvm.so (JVM_NativeLoad+454)
2018-12-09 12:43:51.492 31529-31529/? A/DEBUG:     #16 pc 00022d06  /system/lib/libopenjdk.so (Runtime_nativeLoad+38)
2018-12-09 12:43:51.492 31529-31529/? A/DEBUG:     #17 pc 001149ba  /system/framework/x86/boot.oat (offset 0x114000) (java.lang.Runtime.nativeLoad [DEDUPED]+202)
2018-12-09 12:43:51.492 31529-31529/? A/DEBUG:     #18 pc 005f0d52  /system/lib/libart.so (art_quick_invoke_static_stub+418)
2018-12-09 12:43:51.492 31529-31529/? A/DEBUG:     #19 pc 000a30df  /system/lib/libart.so (art::ArtMethod::Invoke(art::Thread*, unsigned int*, unsigned int, art::JValue*, char const*)+239)
2018-12-09 12:43:51.492 31529-31529/? A/DEBUG:     #20 pc 0029bca2  /system/lib/libart.so (art::interpreter::ArtInterpreterToCompiledCodeBridge(art::Thread*, art::ArtMethod*, art::ShadowFrame*, unsigned short, art::JValue*)+338)
shizhen
  • 12,251
  • 9
  • 52
  • 88
Learner
  • 167
  • 10

1 Answers1

2

The syscall wrappers being available in libc is not the same as the kernel making those syscalls available. It would seem that those syscalls are not allowed, as they are not mentioned in SYSCALLS.TXT or SECCOMP_WHITELIST_*.TXT.

https://android.googlesource.com/platform/bionic/+/master/libc

Did you check for errors from your syscalls? Presumably the first one failed with ENOSYS.

EDIT:

If you look at the most recent copy of this header the comments explain this: https://android.googlesource.com/platform/bionic/+/master/libc/include/sys/shm.h. Those haven't made it into a released NDK yet though.

Dan Albert
  • 10,079
  • 2
  • 36
  • 79
  • IMHO, adding these wrappers to NDK libc was a mistake. – Alex Cohn Dec 12 '18 at 20:06
  • The motivation for adding them was that there are projects out there that need shm.h to compile, but still run fine as long as you don't use those parts of the project. strace, as an example. – Dan Albert Dec 12 '18 at 21:19
  • hm.. do they sniff for ENOSYS? Or they have some compile-time switch that says that ifdef ANDROID, don't use shm? – Alex Cohn Dec 12 '18 at 22:11
  • Since the counter-intelligence of SO seems to knee-jerk delete answers that are not long enough, I will repeat this as a comment: *If you need **shmem** in your library, try this [project](https://github.com/pelya/android-shmem) on GitHub.* Disclaimer: I never tried to run this emulation on API 27, and I cannot tell if the specific emulation does resolve the requirements for your project. – Alex Cohn Dec 13 '18 at 08:56
  • Thanks for your answers @DanAlbert & Alex, Thanks for editing the question Shizhen. I'm not sure what ENOSYS is and how can I look for it. Anyhow i'll try the project mentioned by Alex & see if it works for our requirement. I just want to mention my disappointment with Android here as this is a bit misleading during the porting process and the version of shm header that I have doesn't mention that they are not supported. Thank you again for your time. – Learner Dec 13 '18 at 12:28
  • 1
    I am afraid nobody will see the comments in shm.h as long as the file compiles. And even if it produces warnings, very few will notice. – Alex Cohn Dec 13 '18 at 21:53
  • @AlexCohn yes Alex, I didn't bother about the file as long as the code compiled, but dug into it further after I was getting the crashes due to 'shmget'. Thanks again for your time and answers. – Learner Dec 14 '18 at 06:47
  • @AlexCohn, My project also uses other Sys V IPC features, like semaphores and message queues. Can any of you please suggest the alternatives for Sys V Semaphore APIs (semget(), semop() & semctl()) and the Sys V message queue APIs (msgget(), msgsnd(), msgctl() & msgget()). – Learner Dec 14 '18 at 09:21
  • Maybe you need to reconsider your approach. In Android, there is no much sense in semaphores et al because each app runs in its own sandbox, separated by uid. – Alex Cohn Dec 14 '18 at 10:59
  • Without knowing the context, it's hard to help you. But it's quite possible that all multi-process features are simply not relevant for the Android port. – Alex Cohn Dec 14 '18 at 14:44
  • @AlexCohn, I'll try to explain briefly, our application to be ported uses lots of threads which uses Sys V IPC (& we don't have a fork(), threads only, no new processes with fork()). As part of porting how can we achieve this IPC between the threads as currently Shared Memory, Semaphores & Message Queues are all used. The project on Github solved Shared Memory though, how about the other two. – Learner Dec 15 '18 at 07:30
  • @AlexCohn, I wasn't aware that Android supports POSIX IPC semaphores, as I tried to find the alternatives I found that POSIX semaphore APIs are provided by Android. This is a great news :) I'm now using POSIX semaphore calls instead of unsupported Sys V IPC API's. Thanks for your time everyone... – Learner Dec 15 '18 at 10:58
  • 1
    If you only have one process, the sys V IPC APIs are an overkill, they may be leftovers from the times when pthread API was less popular. You can emulate shmem, semaphores, and message queue for single process, to keep the core code as is. – Alex Cohn Dec 15 '18 at 11:22
  • "hm.. do they sniff for ENOSYS? Or they have some compile-time switch that says that ifdef ANDROID, don't use shm?" The latter or neither, typically. Or they'll check something only semi-related like `EPOLL_CLOEXEC` for the existence of `epoll_create1`. Checking for `ENOSYS` would be the right approach, but people often won't fix problems that are only symptomatic for Android. – Dan Albert Dec 17 '18 at 18:34