Skip to content

Commit 31fe91d

Browse files
[nativeaot] set $HOME and $TMPDIR (#9889)
Context: #9846 Context: https://github.com/dotnet/runtime/blob/d09a42b9149e14a37c8ef8363cdb7e17bb922c37/src/libraries/System.Private.CoreLib/src/System/IO/Path.Unix.cs#L83 `System.IO.Path.GetTempPath()` doesn't work under NativeAOT as seen by the test failure: Mono.Android.NET_Tests, Android.RuntimeTests.InputStreamInvokerTest.InputStreamTest / Release System.IO.DirectoryNotFoundException : IO_PathNotFound_Path, /tmp/ at Interop.ThrowExceptionForIoErrno(Interop.ErrorInfo, String, Boolean) + 0x11 at Interop.CheckIo(Int64, String, Boolean) + 0x5d at System.IO.Path.GetTempFileName() + 0x14d at Android.RuntimeTests.InputStreamInvokerTest.InputStreamTest() + 0x18 at libMono.Android.NET-Tests!<BaseAddress>+0x1483023 at System.Reflection.DynamicInvokeInfo.Invoke(Object, IntPtr, Object[], BinderBundle, Boolean) + 0xf3 On Unix-like systems, the BCL just reads `$TMPDIR` and falls back to `/tmp/` if it doesn't exist. `$TMPDIR` is *not* set by default in Android applications. To fix this, we can set `$TMPDIR` to `context.getCacheDir()` just as we do in .NET for Android: * https://github.com/dotnet/android/blob/04cd6f40989a8fad30d9a9759aec02d540cc9478/src/java-runtime/java/mono/android/MonoPackageManager.java#L53-L54 * https://github.com/dotnet/android/blob/04cd6f40989a8fad30d9a9759aec02d540cc9478/src/native/mono/monodroid/monodroid-glue.cc#L1444-L1445 I think we can simply read these values in Java at startup, and call [`Os.setenv()`][0] to set them. There does not seem to be a need to pass these paths into managed code. The `Android.RuntimeTests.InputStreamInvokerTest.InputStreamTest()` test now passes with these changes. I fixed `$HOME` as well, as it will be used by other APIs in the BCL. [0]: https://developer.android.com/reference/android/system/Os#setenv(java.lang.String,%20java.lang.String,%20boolean)
1 parent 1d099e7 commit 31fe91d

File tree

1 file changed

+14
-0
lines changed

1 file changed

+14
-0
lines changed

src/Xamarin.Android.Build.Tasks/Resources/NativeAotRuntimeProvider.java

+14
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
package net.dot.jni.nativeaot;
22

3+
import android.system.ErrnoException;
4+
import android.system.Os;
35
import android.util.Log;
46
import net.dot.android.ApplicationRegistration;
57

@@ -24,6 +26,18 @@ public void attachInfo(android.content.Context context, android.content.pm.Provi
2426
if (context instanceof android.app.Application) {
2527
ApplicationRegistration.Context = context;
2628
}
29+
30+
// Set environment variables
31+
try {
32+
String filesDir = context.getFilesDir().getAbsolutePath();
33+
String cacheDir = context.getCacheDir().getAbsolutePath();
34+
Os.setenv("HOME", filesDir, true);
35+
Os.setenv("TMPDIR", cacheDir, true);
36+
} catch (ErrnoException e) {
37+
Log.e(TAG, "Failed to set environment variables", e);
38+
}
39+
40+
// Initialize .NET runtime
2741
JavaInteropRuntime.init();
2842
// NOTE: only required for custom applications
2943
ApplicationRegistration.registerApplications();

0 commit comments

Comments
 (0)