-
Notifications
You must be signed in to change notification settings - Fork 1.2k
[android] Implement Process and modify TestProcess to pass. #2228
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
@swift-ci please test |
TestFoundation/TestProcess.swift
Outdated
if let ldLibraryPath = ProcessInfo.processInfo.environment["LD_LIBRARY_PATH"] { | ||
process.environment?["LD_LIBRARY_PATH"] = ldLibraryPath | ||
} | ||
#endif | ||
process.launch() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is the LD_LIBRARY_PATH
still needed? When I updated xdgTestHelper
to contain all of the utilities I updated the CMakeLists.txt
to add an rpath
to the build directory which should apply to both Linux and Android:
set(XDG_TEST_HELPER_RPATH -Xlinker;-rpath;-Xlinker;${CMAKE_CURRENT_BINARY_DIR})
This was needed because one of the tests clears the environment before calling xdgTestHelper --env
and before adding in the rpath
it was failing as the LD_LIBRARY_PATH
was not set anymore.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
${CMAKE_CURRENT_BINARY_DIR}
is a path in the build machine, but it doesn’t mean anything when moving the executable to the device for testing. That's also why this pieces are restricted to Android (they should not be needed for other targets).
Foundation CMakeLists is not prepared to test in Android, so the testing has to done manually, and while I always use the same directory, I would prefer not to hardcode anything in the CMakeLists for Android (I have to figure out how to simplify testing for Android).
Foundation/Process.swift
Outdated
@@ -978,4 +979,127 @@ private func posix(_ code: Int32) { | |||
default: fatalError("POSIX command failed with error: \(code)") | |||
} | |||
} | |||
|
|||
#if os(Android) | |||
// Android doesn't provide posix_spawn APIs until recent API level, so we cannot |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do you want to delegate to the real API if they exist?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don’t know if one can do that.
The availability of the symbol depends on the Android API level. By default, if nobody sets a different __ANDROID_API__
while compiling, the latest API level is used. Swift sets API level 21, but Foundation doesn't set anything, so at the moment, Foundation is being compiled with access to every available symbol in the Android NDK (I'm not 100% sure about that, though, because I don’t know if the module cache remembers the setting from Swift). So the symbol will be available at compile time, but it might not be at runtime (and the binary will probably fail to start).
I don’t think #available/@available
works for Android, which might be a good way, so I think this is the best I can come up now.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think that it makes sense to pass along the __ANDROID_API__
when building for Android. Using posix_spawn
is preferable to rolling our own.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't understand where you exactly want to pass __ANDROID_API__
. Swift definitions are just booleans, and there's no support for something like #if __ANDROID_API__ >= 21
, IIRC.
We might be able to do those checks in CoreFoundation, but again __ANDROID_API__
is not a runtime check, but a "minimum deployment target" compilation check. When compiling you are deciding which is the minimal API you want to deploy to. As the code is written, we are supporting API levels before 26. If I use posix_spawn (and link against it), then we are not supporting anything before level 26.
That's my understanding, unless someone has another theory.
I'm okay with this patch otherwise. |
4f9a3bf
to
4556534
Compare
Added the feedback from Simon. @swift-ci please test |
Tested this with the 5/12 snapshot, Process tests all passing now, whereas before I had to put in more workarounds just to avoid those tests on Android AArch64:
|
4556534
to
4793d93
Compare
Rebased on top of master and removed the conflict. This change do not include any changes to the @swift-ci please test |
@swift-ci please test |
Foundation/Process.swift
Outdated
@@ -978,4 +979,127 @@ private func posix(_ code: Int32) { | |||
default: fatalError("POSIX command failed with error: \(code)") | |||
} | |||
} | |||
|
|||
#if os(Android) | |||
// Android doesn't provide posix_spawn APIs until recent API level, so we cannot |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think that it makes sense to pass along the __ANDROID_API__
when building for Android. Using posix_spawn
is preferable to rolling our own.
Foundation/Process.swift
Outdated
|
||
// Clean up the parent signal handlers | ||
for idx in 1..<(NSIG as Int32) { | ||
// Seems that SIGKILL/SIGSTOP are sometimes silently ignored, and |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Odd, is that a documented issue on android?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not that I know of. I found it doing trial and error. Some device was fine, some other was crashing here.
In https://pubs.opengroup.org/onlinepubs/009695399/functions/sigaction.html there's discussion that they should be ignored silently, but it also talks about SysV and BSD returning EINVAL. I think the problem is that, in the code I found for Bionic, it seems to delegate to Linux rt_sigaction
, which is documented to fail for those two signals.
In any case, since SIGKILL
and SIGSTOP
cannot be ignored or caught, they are already set to SIG_DFL
, which is what this code will try to do. Skipping them should not have ill effects.
4793d93
to
14aeae5
Compare
@swift-ci please test linux platform |
14aeae5
to
9e365ad
Compare
All right. I rewrote all the code in a way I hope matches the requests above. Instead always using a custom @compnerd: can you review if this is what you wanted? |
Until recent API levels, Android haven't provide posix_spawn and other functions from that family, so Process was not going to work with the branches used for other POSIX OS. Instead of creating an specific path for Android, which will probably be forgotten by other changes, all the POSIX OS will use private CF functions that wrap the posix_spawn functions. For Android, we try to figure out if posix_spawn exist, and use it in that case, but we implement a subset of the posix_spawn family of functions for lower API levels, using fork and exec underneath, and other functions from the POSIX APIs. The already code in Process is only modified slightly to adapt to the new names have to be modified. The tests have to be modified slightly for working on Android. Many changes are related to the environment needing the key LD_LIBRARY_PATH, or the xdgTestHelper will not be able to start in some of the tests. The other change is using NSTemporaryDirectory() instead of a hardcoded `/tmp`, which doesn't exist in Android (the code also removes the last slash, to match the original code expectations). It also includes a small fix for when launch() is used and a error is thrown which is not related to the current working directory. Before the error was ignored silently, and now it will fatalError. Other small improvement is reporting the actual line in the helper for the returned POSIX error codes, instead of always reporting the line of the helper itself.
9e365ad
to
79019d2
Compare
Rebased to avoid conflicts with master. Ready for review. @swift-ci please test Linux platform |
Failures in LLDB are unrelated. @swift-ci please test Linux platform |
Until recent API levels, Android haven't provide posix_spawn and other
functions from that family, so Process was not going to work with the
branches used for other POSIX OS.
Instead of creating an specific path for Android, which will probably be
forgotten by other changes, all the POSIX OS will use private CF
functions that wrap the posix_spawn functions. For Android, we try to
figure out if posix_spawn exist, and use it in that case, but we
implement a subset of the posix_spawn family of functions for lower API
levels, using fork and exec underneath, and other functions from the
POSIX APIs. The already code in Process is only modified slightly to
adapt to the new names have to be modified.
The tests have to be modified slightly for working on Android. Many
changes are related to the environment needing the key LD_LIBRARY_PATH,
or the xdgTestHelper will not be able to start in some of the tests. The
other change is using NSTemporaryDirectory() instead of a hardcoded
/tmp
, which doesn't exist in Android (the code also removes the lastslash, to match the original code expectations).
It also includes a small fix for when launch() is used and a error is
thrown which is not related to the current working directory. Before the
error was ignored silently, and now it will fatalError.
Other small improvement is reporting the actual line in the helper for
the returned POSIX error codes, instead of always reporting the line of
the helper itself.
Special thanks to @spevans because without the recent changes to use exclusively xdgTestHelper, the changes in the tests would have been more complicated.