Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ parameters:
jobs:

#
# Build CoreCLR + libraries for WASI (wasm32-wasi).
# Build CoreCLR + libraries for WASI (wasm32-wasip2).
#
# Produces a runtime pack + corerun.wasm artifact under
# wasi.wasm.Release. The companion pipeline that actually runs the
Expand Down
1 change: 0 additions & 1 deletion eng/testing/tests.wasi.targets
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,6 @@
<_XHarnessArgs >$(_XHarnessArgs) --engine-arg=--wasi --engine-arg=udp</_XHarnessArgs>
<_XHarnessArgs >$(_XHarnessArgs) --engine-arg=--wasi --engine-arg=allow-ip-name-lookup</_XHarnessArgs>
<_XHarnessArgs >$(_XHarnessArgs) --engine-arg=--wasi --engine-arg=hostcall-fuel=4294967295</_XHarnessArgs>
<_XHarnessArgs >$(_XHarnessArgs) --engine-arg=--env --engine-arg=DOTNET_WASI_PRINT_EXIT_CODE=1</_XHarnessArgs>
<!-- CoreCLR-WASI: enable the wasm exception-handling proposal (the host relies on it)
and point the host at the bundled framework via CORE_ROOT=/managed. Validated
locally: host+runtime live in managed/ and init succeeds under wasmtime. -->
Expand Down
2 changes: 1 addition & 1 deletion eng/wasm/wasi-sdk-version.txt
Original file line number Diff line number Diff line change
@@ -1 +1 @@
33.0
34.0
22 changes: 6 additions & 16 deletions src/coreclr/hosts/corerun/corerun.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -654,22 +654,6 @@ static int run(const configuration& config)
return exit_code;
#else // TARGET_BROWSER
int final_exit_code = corerun_shutdown(exit_code);
#ifdef TARGET_WASI
// wasi:cli/exit's stable exit() only signals ok/err, so wasmtime
// collapses any non-zero Main return to host exit 1. When
// DOTNET_WASI_PRINT_EXIT_CODE=1, emit a "WASM EXIT <n>" marker on
// stderr matching Mono (src/mono/wasi/runtime/main.c); the WASI
// launcher in src/tests/Common/CLRTest.Execute.Bash.targets recovers
// the value from that. wasi:cli/exit already defines
// exit-with-code(status-code: u8), but it is gated
// @unstable(feature = cli-exit-with-code) in wasi-cli 0.2.x. Once that
// feature stabilizes and wasi-libc/wasi-sdk/wasmtime expose it, this
// marker (and the parser in CLRTest.Execute.Bash.targets) can be removed.
if (pal::getenv(W("DOTNET_WASI_PRINT_EXIT_CODE")) == W("1"))
{
pal::fprintf(stderr, W("WASM EXIT %d\n"), final_exit_code);
}
#endif // TARGET_WASI
return final_exit_code;
#endif // TARGET_BROWSER
}
Expand Down Expand Up @@ -879,7 +863,13 @@ int MAIN(const int argc, const char_t* argv[])
return self_test();

int exit_code = run(config);
#ifdef TARGET_WASI
// Returning from main only reports success/failure through wasi:cli/run.
// exit() reports the actual code through wasi:cli/exit's exit-with-code.
exit(exit_code);
#else
return exit_code;
#endif
}

extern "C" DLL_EXPORT HRESULT CDECL GetCurrentClrDetails(void** clrInstance, unsigned int* appDomainId)
Expand Down
5 changes: 4 additions & 1 deletion src/coreclr/runtime.proj
Original file line number Diff line number Diff line change
Expand Up @@ -116,13 +116,16 @@
<_CoreClrBuildScript Condition="$([MSBuild]::IsOsPlatform(Windows))">build-runtime.cmd</_CoreClrBuildScript>
<_CoreClrBuildScript Condition="!$([MSBuild]::IsOsPlatform(Windows))">build-runtime.sh</_CoreClrBuildScript>
<_CoreClrBuildCommand>&quot;$(MSBuildThisFileDirectory)$(_CoreClrBuildScript)&quot; @(_CoreClrBuildArg, ' ') @(NativeCMakeArg, ' ')</_CoreClrBuildCommand>
<_CoreClrBuildEnvironmentVariables>EMSDK_PATH=$(EMSDK_PATH)</_CoreClrBuildEnvironmentVariables>
<!-- Use the SDK resolved by AcquireWasiSdk rather than a preinstalled $(WASI_SDK_PATH) of a different version. -->
<_CoreClrBuildEnvironmentVariables Condition="'$(TargetsWasi)' == 'true'">$(_CoreClrBuildEnvironmentVariables);WASI_SDK_PATH=$(RuntimeBuildWasiSdkPath)</_CoreClrBuildEnvironmentVariables>
</PropertyGroup>

<!-- Use IgnoreStandardErrorWarningFormat because Arcade sets WarnAsError and we want to avoid upgrading compiler warnings to errors in release branches -->
<Message Text="Executing $(_CoreClrBuildCommand)" Importance="High" />
<Exec Command="$(_CoreClrBuildCommand)"
IgnoreStandardErrorWarningFormat="true"
EnvironmentVariables="EMSDK_PATH=$(EMSDK_PATH)"
EnvironmentVariables="$(_CoreClrBuildEnvironmentVariables)"
/>
</Target>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -123,11 +123,13 @@ internal struct tcp_socket_state_t
}

// Layout mirrors wasi-libc (WASIp2) tcp_socket_t from
// https://github.com/WebAssembly/wasi-libc/blob/161b3195fc25/libc-bottom-half/headers/private/wasi/tcp.h
// https://github.com/WebAssembly/wasi-libc/blob/2e6fb9d8ee0c/libc-bottom-half/headers/private/wasi/tcp.h
// Only `socket`, `state` and `socket_pollable` are read; trailing fields are modelled for completeness.
// The `lock` field that follows `refcnt` is empty in the single-threaded wasm32-wasip2 libc.
[StructLayout(LayoutKind.Sequential)]
internal struct tcp_socket_t
{
public uint refcnt;
public tcp_own_tcp_socket_t socket;
public tcp_socket_state_t state;
public poll_own_pollable_t socket_pollable;
Expand Down Expand Up @@ -197,15 +199,19 @@ internal struct udp_socket_state_t
}

// Layout mirrors wasi-libc (WASIp2) udp_socket_t from
// https://github.com/WebAssembly/wasi-libc/blob/161b3195fc25/libc-bottom-half/sources/udp.c
// https://github.com/WebAssembly/wasi-libc/blob/2e6fb9d8ee0c/libc-bottom-half/sources/udp.c
// The `lock` field that follows `refcnt` is empty in the single-threaded wasm32-wasip2 libc.
[StructLayout(LayoutKind.Sequential)]
internal struct udp_socket_t
{
public uint refcnt;
public udp_own_udp_socket_t socket;
public poll_own_pollable_t socket_pollable;
public byte blocking;
public byte family;
public udp_socket_state_t state;
public ulong send_timeout;
public ulong recv_timeout;
}

public sealed partial class UnixHandleAsyncContext
Expand Down
3 changes: 1 addition & 2 deletions src/mono/sample/wasi/Directory.Build.targets
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
<_SampleAssembly Condition="'$(_SampleAssembly)' == ''">$(TargetFileName)</_SampleAssembly>
<_SampleProjectName>$([System.String]::Copy('$(_SampleProject)').Replace('.csproj',''))</_SampleProjectName>
<_MONO_LOG_LEVEL Condition="false">--env MONO_LOG_LEVEL=debug --env MONO_LOG_MASK=all</_MONO_LOG_LEVEL>
<_DOTNET_WASI_PRINT_EXIT_CODE>--env DOTNET_WASI_PRINT_EXIT_CODE=1</_DOTNET_WASI_PRINT_EXIT_CODE>
</PropertyGroup>

<Target Name="BuildSampleInTree"
Expand Down Expand Up @@ -35,7 +34,7 @@
<_DotnetWasmName>dotnet.wasm</_DotnetWasmName>
<_DotnetWasmName Condition="'$(WasmSingleFileBundle)' == 'true'">$([System.IO.Path]::ChangeExtension($(_SampleAssembly), '.wasm'))</_DotnetWasmName>
<_AppBundlePath>$([MSBuild]::NormalizeDirectory('bin/wasi-wasm/AppBundle'))</_AppBundlePath>
<WasiCommand>$(WasmtimeDir)wasmtime$(_ExeExt) $(_MONO_LOG_LEVEL) $(_DOTNET_WASI_PRINT_EXIT_CODE)</WasiCommand>
<WasiCommand>$(WasmtimeDir)wasmtime$(_ExeExt) $(_MONO_LOG_LEVEL)</WasiCommand>


<WasiCommand Condition="'$(_WasiNeedsHttp)' == 'true'" >$(WasiCommand) --wasi http</WasiCommand>
Expand Down
2 changes: 1 addition & 1 deletion src/mono/wasi/build/WasiApp.targets
Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,7 @@
</ReadLinesFromFile>
<PropertyGroup>
<!-- In-tree builds override this from eng/wasm/wasi-sdk-version.txt via WasiApp.InTree.targets. -->
<_ExpectedWasiSdkVersion Condition="'$(_ExpectedWasiSdkVersion)' == ''">33.0</_ExpectedWasiSdkVersion>
<_ExpectedWasiSdkVersion Condition="'$(_ExpectedWasiSdkVersion)' == ''">34.0</_ExpectedWasiSdkVersion>
<_FoundExpectedWasiSdkVersion Condition="$([System.String]::Copy('%(_WasiSdkVersionLines.Identity)').StartsWith('$(_ExpectedWasiSdkVersion)'))">true</_FoundExpectedWasiSdkVersion>
<_ToolchainMissingErrorMessage Condition="'$(_FoundExpectedWasiSdkVersion)' == ''">Please use wasi-sdk version $(_ExpectedWasiSdkVersion) and set %24(WASI_SDK_PATH) . It can be obtained from https://github.com/WebAssembly/wasi-sdk/releases</_ToolchainMissingErrorMessage>
<_ToolchainMissingErrorMessage Condition="'$(WASI_SDK_PATH)' == '' or !Exists('$(WASI_SDK_PATH)/VERSION')">Could not find wasi-sdk. Install wasi-sdk and set %24(WASI_SDK_PATH) . It can be obtained from https://github.com/WebAssembly/wasi-sdk/releases</_ToolchainMissingErrorMessage>
Expand Down
12 changes: 3 additions & 9 deletions src/mono/wasi/runtime/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@

// This symbol's implementation is generated during the build
const char* dotnet_wasi_getentrypointassemblyname();
char *monoeg_g_getenv(const char *variable);

#ifdef WASI_AFTER_RUNTIME_LOADED_DECLARATIONS
// This is supplied from the MSBuild itemgroup @(WasiAfterRuntimeLoaded)
Expand Down Expand Up @@ -121,13 +120,8 @@ int main(int argc, char * argv[]) {
}
ret = ret < 0 ? -ret : ret;

// until WASI can work with unix exit code https://github.com/WebAssembly/wasi-cli/pull/44
char* dotnet_wasi_print_exit_code = monoeg_g_getenv ("DOTNET_WASI_PRINT_EXIT_CODE");
if (ret != 0 && dotnet_wasi_print_exit_code && strcmp(dotnet_wasi_print_exit_code, "1") == 0)
{
fprintf(stderr, "WASM EXIT %d\n", ret);
}

return ret;
// Returning from main only reports success/failure through wasi:cli/run.
// exit() reports the actual code through wasi:cli/exit's exit-with-code.
exit(ret);
}
#endif
2 changes: 1 addition & 1 deletion src/mono/wasi/wasmtime-version.txt
Original file line number Diff line number Diff line change
@@ -1 +1 @@
45.0.0
49.0.1
18 changes: 1 addition & 17 deletions src/mono/wasm/host/wasi/WasiEngineArguments.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,8 @@
// The .NET Foundation licenses this file to you under the MIT license.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.Json;
using Mono.Options;

namespace Microsoft.WebAssembly.AppHost;

Expand All @@ -14,7 +12,6 @@ internal sealed class WasiEngineArguments
public WasmHost Host => CommonConfig.Host;
public CommonConfiguration CommonConfig { get; init; }

public bool ForwardExitCode { get; private set; }
public string[] AppArgs { get; init; }

public bool IsSingleFileBundle =>
Expand All @@ -24,20 +21,7 @@ internal sealed class WasiEngineArguments
public WasiEngineArguments(CommonConfiguration commonConfig)
{
CommonConfig = commonConfig;
AppArgs = GetOptions().Parse(commonConfig.RemainingArgs).ToArray();
ParseJsonProperties(CommonConfig.HostConfig.Properties);
}

private OptionSet GetOptions() => new OptionSet
{
// until WASI can work with unix exit code https://github.com/WebAssembly/wasi-cli/pull/44
{ "forward-exit-code", "Forward process exit code via stderr", v => ForwardExitCode = true }
};

public void ParseJsonProperties(IDictionary<string, JsonElement>? properties)
{
if (properties?.TryGetValue("forward-exit-code", out JsonElement forwardElement) == true)
ForwardExitCode = forwardElement.GetBoolean();
AppArgs = commonConfig.RemainingArgs.ToArray();
}

public void Validate()
Expand Down
23 changes: 3 additions & 20 deletions src/mono/wasm/host/wasi/WasiEngineHost.cs
Original file line number Diff line number Diff line change
Expand Up @@ -58,11 +58,6 @@ private async Task<int> RunAsync()
args.AddRange(["--dir", "."]);
};

if (_args.ForwardExitCode)
{
args.AddRange(["--env", "DOTNET_WASI_PRINT_EXIT_CODE=1"]);
};

args.AddRange(_args.CommonConfig.HostArguments);

args.Add("--");
Expand All @@ -89,23 +84,11 @@ private async Task<int> RunAsync()
foreach (string? arg in args)
psi.ArgumentList.Add(arg!);

int? exitCodeOverride = null;
int exitCode = await Utils.TryRunProcess(psi,
_logger,
msg => { if (msg != null) _logger.LogInformation(msg); },
msg => {
if (msg != null) {
if (_args.ForwardExitCode && msg.StartsWith("WASM EXIT "))
{
exitCodeOverride = int.Parse(msg.Substring(10));
}
else
{
_logger.LogInformation(msg);
}
}
});

return exitCodeOverride ?? exitCode;
msg => { if (msg != null) _logger.LogInformation(msg); });

return exitCode;
}
}
13 changes: 4 additions & 9 deletions src/native/corehost/wasihost/wasihost.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

#include <cstdint>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <set>
#include <sstream>
Expand Down Expand Up @@ -41,7 +42,6 @@ namespace envvar
{
const char_t* const coreRoot = W("CORE_ROOT");
const char_t* const coreLibraries = W("CORE_LIBRARIES");
const char_t* const printExitCode = W("DOTNET_WASI_PRINT_EXIT_CODE");
}

// Statically linked at the per-app relink, so declared extern here (as browserhost does).
Expand Down Expand Up @@ -308,12 +308,7 @@ int main(int argc, char* argv[])
latched_exit_code = -1;
}

// wasi:cli/exit's exit() only signals ok/err, so wasmtime collapses a non-zero result to host
// exit 1. Under DOTNET_WASI_PRINT_EXIT_CODE=1, emit a "WASM EXIT <n>" marker the WASI launcher
// parses (matching Mono). exit-with-code is stable in WASI 0.3 but still @unstable in the wasip2
// world this targets; see corerun.cpp.
if (pal::getenv(envvar::printExitCode) == W("1"))
std::fprintf(stderr, "WASM EXIT %d\n", latched_exit_code);

return latched_exit_code;
// Returning from main only reports success/failure through wasi:cli/run.
// exit() reports the actual code through wasi:cli/exit's exit-with-code.
std::exit(latched_exit_code);
}
32 changes: 23 additions & 9 deletions src/native/libs/System.Native/pal_networking.c
Original file line number Diff line number Diff line change
Expand Up @@ -3091,11 +3091,16 @@ int32_t SystemNative_Select(int* readFds, int readFdsCount, int* writeFds, int w
}

#if defined(TARGET_WASI)
// from https://github.com/WebAssembly/wasi-libc/blob/161b3195fc25/libc-bottom-half/headers/private/wasi/descriptor_table.h
// The descriptor table entry is a "fat pointer":
// typedef struct { void* data; descriptor_vtable_t* vtable; } descriptor_table_entry_t;
// where `data` points to the descriptor-specific state (a tcp_socket_t* or udp_socket_t*).
void* descriptor_table_get_ref(int fd);
// from https://github.com/WebAssembly/wasi-libc/blob/2e6fb9d8ee0c/libc-bottom-half/headers/private/wasi/descriptor_table.h
// The descriptor table entry is a "fat pointer" where `data` points to the descriptor-specific
// state (a tcp_socket_t* or udp_socket_t*), which starts with a reference count.
typedef struct
{
unsigned* data;
void* vtable;
} WasiDescriptorTableEntry;
int descriptor_table_get(int fd, WasiDescriptorTableEntry* entry);
void __wasilibc_descriptor_deallocate(WasiDescriptorTableEntry entry);

// this method is invading private implementation details of wasi-libc
// we could get rid of it when https://github.com/WebAssembly/wasi-libc/issues/542 is resolved
Expand All @@ -3112,14 +3117,23 @@ int32_t SystemNative_GetWasiSocketDescriptor(intptr_t socket, void** entry, int3
}

int fd = ToFileDescriptor(socket);
// The returned pointer is a descriptor_table_entry_t*; its first word is the `data` pointer.
void** ref = (void**)descriptor_table_get_ref(fd);
if (ref == NULL)
WasiDescriptorTableEntry tableEntry;
if (descriptor_table_get(fd, &tableEntry) != 0)
{
// The fd is not present in the descriptor table (e.g. closed or not a socket).
return Error_EBADF;
}
*entry = ref[0];

// descriptor_table_get returns a strong reference. The descriptor table still holds its own
// reference while the fd is open, so release ours (mirroring descriptor_table_entry_dec) and
// hand out a borrowed pointer, which is how the managed side uses it.
*entry = tableEntry.data;
if (--(*tableEntry.data) == 0)
{
__wasilibc_descriptor_deallocate(tableEntry);
*entry = NULL;
return Error_EBADF;
}

int type = 0;
socklen_t length = sizeof(type);
Expand Down
Loading
Loading