diff --git a/src/windows/WslcSDK/wslcsdk.h b/src/windows/WslcSDK/wslcsdk.h index 2cec8d2cd..2abbbc8b4 100644 --- a/src/windows/WslcSDK/wslcsdk.h +++ b/src/windows/WslcSDK/wslcsdk.h @@ -477,7 +477,7 @@ typedef struct WslcImageInfo // we should expose this CHAR name[WSLC_IMAGE_NAME_LENGTH]; uint8_t sha256[32]; - uint64_t sizeBytes; + int64_t sizeBytes; uint64_t createdUnixTime; } WslcImageInfo; diff --git a/src/windows/common/WSLCContainerLauncher.cpp b/src/windows/common/WSLCContainerLauncher.cpp index 51826ebd4..dc68e69c2 100644 --- a/src/windows/common/WSLCContainerLauncher.cpp +++ b/src/windows/common/WSLCContainerLauncher.cpp @@ -129,7 +129,7 @@ void WSLCContainerLauncher::SetDefaultStopSignal(WSLCSignal Signal) m_stopSignal = Signal; } -void WSLCContainerLauncher::SetShmSize(ULONGLONG ShmSize) +void WSLCContainerLauncher::SetShmSize(int64_t ShmSize) { m_shmSize = ShmSize; } diff --git a/src/windows/common/WSLCContainerLauncher.h b/src/windows/common/WSLCContainerLauncher.h index e31521115..ee52fcd2f 100644 --- a/src/windows/common/WSLCContainerLauncher.h +++ b/src/windows/common/WSLCContainerLauncher.h @@ -73,7 +73,7 @@ class WSLCContainerLauncher : private WSLCProcessLauncher void SetName(std::string&& Name); void SetEntrypoint(std::vector&& entrypoint); void SetDefaultStopSignal(WSLCSignal Signal); - void SetShmSize(ULONGLONG ShmSize); + void SetShmSize(int64_t ShmSize); void SetContainerFlags(WSLCContainerFlags Flags); void SetContainerNetworkName(std::string&& Name); void SetHostname(std::string&& Hostname); @@ -102,7 +102,7 @@ class WSLCContainerLauncher : private WSLCProcessLauncher std::string m_containerNetworkName; std::vector m_entrypoint; WSLCSignal m_stopSignal = WSLCSignalNone; - ULONGLONG m_shmSize = 0; + int64_t m_shmSize = 0; WSLCContainerFlags m_containerFlags = WSLCContainerFlagsNone; std::string m_hostname; std::string m_domainname; diff --git a/src/windows/inc/docker_schema.h b/src/windows/inc/docker_schema.h index 916524b0e..ea15bfe79 100644 --- a/src/windows/inc/docker_schema.h +++ b/src/windows/inc/docker_schema.h @@ -9,7 +9,8 @@ Module Name: Abstract: JSON schema for the docker API. - The documentation for the API can be found at: https://docs.docker.com/reference/api/engine/version/v1.52/#tag/Container + Targets the daemon API version bundled with WSLC's dockerd (currently v25.0.3, API v1.44). + The documentation for the API can be found at: https://docs.docker.com/reference/api/engine/version/v1.44/#tag/Container --*/ @@ -22,10 +23,9 @@ namespace wsl::windows::common::docker_schema { struct CreatedContainer { std::string Id; - std::string Name; std::vector Warnings; - NLOHMANN_DEFINE_TYPE_INTRUSIVE(CreatedContainer, Id, Warnings); + NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(CreatedContainer, Id, Warnings); }; struct ErrorResponse @@ -83,7 +83,10 @@ struct Volume std::string CreatedAt; std::optional> Options; std::optional> Labels; - std::optional> Status; + // Docker's wire schema for Status is map[string]any: third-party volume + // drivers may set arbitrary JSON values (numbers, bools, objects), not + // just strings. Use nlohmann::json so deserialization never throws. + std::optional> Status; std::optional UsageData; NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(Volume, Name, Driver, Mountpoint, CreatedAt, Options, Labels, Status, UsageData); @@ -223,7 +226,9 @@ struct HostConfig std::optional> DnsOptions; std::optional> Binds; std::map Tmpfs; - std::optional ShmSize; + // Docker wire type is int64. 0 means "use daemon default" — same as omitting + // the field — so we don't bother with std::optional here. + std::int64_t ShmSize{}; std::optional> Devices; // Per-container resource limits. 0 means "no limit" (Docker default). @@ -356,7 +361,7 @@ struct Image std::string Id; std::vector RepoTags; std::vector RepoDigests; - uint64_t Size{}; + int64_t Size{}; int64_t Created{}; std::string ParentId; @@ -432,7 +437,7 @@ struct InspectImage std::string Variant; std::string Os; std::string OsVersion; - uint64_t Size{}; + int64_t Size{}; std::optional GraphDriver; std::optional RootFS; std::optional> Metadata; @@ -455,41 +460,73 @@ struct CreateExec bool AttachStdout{}; bool AttachStderr{}; bool Tty{}; + // Docker wire type is *[2]uint64. Sending an empty array on a TTY exec yields + // a 0x0 console; the field must be omitted entirely when the caller didn't set it. std::vector ConsoleSize; std::vector Cmd; std::vector Env; std::optional User; std::string WorkingDir; std::optional DetachKeys; - - NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(CreateExec, AttachStdin, AttachStdout, AttachStderr, Tty, ConsoleSize, Cmd, Env, WorkingDir, User, DetachKeys); }; +inline void to_json(nlohmann::json& j, const CreateExec& v) +{ + j = nlohmann::json{ + {"AttachStdin", v.AttachStdin}, + {"AttachStdout", v.AttachStdout}, + {"AttachStderr", v.AttachStderr}, + {"Tty", v.Tty}, + {"Cmd", v.Cmd}, + {"Env", v.Env}, + {"WorkingDir", v.WorkingDir}, + {"User", v.User}, + {"DetachKeys", v.DetachKeys}, + }; + + if (!v.ConsoleSize.empty()) + { + j["ConsoleSize"] = v.ConsoleSize; + } +} + struct StartExec { using TResponse = void; bool Tty{}; bool Detach{}; + // See CreateExec::ConsoleSize. std::vector ConsoleSize; - - NLOHMANN_DEFINE_TYPE_INTRUSIVE_ONLY_SERIALIZE(StartExec, Tty, Detach, ConsoleSize); }; +inline void to_json(nlohmann::json& j, const StartExec& v) +{ + j = nlohmann::json{{"Tty", v.Tty}, {"Detach", v.Detach}}; + + if (!v.ConsoleSize.empty()) + { + j["ConsoleSize"] = v.ConsoleSize; + } +} + enum class ContainerState { + Unknown, Created, Running, Paused, Restarting, Exited, Removing, - Dead, - Unknown + Dead }; NLOHMANN_JSON_SERIALIZE_ENUM( ContainerState, { + // Unknown is first so unrecognized strings (or missing field) deserialize to Unknown, + // not to whatever the next entry happens to be. + {ContainerState::Unknown, nullptr}, {ContainerState::Created, "created"}, {ContainerState::Running, "running"}, {ContainerState::Paused, "paused"}, @@ -580,7 +617,7 @@ struct CreateImageProgress }; // Container stats (GET /containers/{id}/stats?stream=false) -// See: https://docs.docker.com/reference/api/engine/version/v1.52/#tag/Container/operation/ContainerStats +// See: https://docs.docker.com/reference/api/engine/version/v1.44/#tag/Container/operation/ContainerStats struct ContainerStatsCpuUsage { diff --git a/src/windows/inc/wslc_schema.h b/src/windows/inc/wslc_schema.h index f5576391c..3309b6d32 100644 --- a/src/windows/inc/wslc_schema.h +++ b/src/windows/inc/wslc_schema.h @@ -136,7 +136,7 @@ struct InspectImage std::string Author; std::string Architecture; std::string Os; - uint64_t Size{}; + int64_t Size{}; std::optional> Metadata; std::optional Config; diff --git a/src/windows/service/inc/wslc.idl b/src/windows/service/inc/wslc.idl index 2ad3216f8..699e659a8 100644 --- a/src/windows/service/inc/wslc.idl +++ b/src/windows/service/inc/wslc.idl @@ -122,7 +122,7 @@ typedef struct _WSLCImageInformation char Image[WSLC_MAX_IMAGE_NAME_LENGTH + 1]; char Hash[256]; char Digest[256]; - ULONGLONG Size; + LONGLONG Size; // Matches Docker's int64 image size LONGLONG Created; // Unix timestamp char ParentId[256]; } WSLCImageInformation; @@ -301,7 +301,7 @@ typedef struct _WSLCContainerOptions WSLCStringArray DnsSearchDomains; WSLCStringArray DnsOptions; - ULONGLONG ShmSize; + LONGLONG ShmSize; // Matches Docker's int64 ShmSize; consistent with MemoryBytes/NanoCpus WSLCContainerNetwork ContainerNetwork; [unique, size_is(TmpfsCount)] const WSLCTmpfsMount* Tmpfs; ULONG TmpfsCount; diff --git a/src/windows/wslc/arguments/ArgumentValidation.cpp b/src/windows/wslc/arguments/ArgumentValidation.cpp index 28fab0b22..5604d685e 100644 --- a/src/windows/wslc/arguments/ArgumentValidation.cpp +++ b/src/windows/wslc/arguments/ArgumentValidation.cpp @@ -248,7 +248,7 @@ void ValidateMemorySize(const std::vector& values, const std::wstr } } -ULONGLONG GetMemorySizeFromString(const std::wstring& input, const std::wstring& argName) +int64_t GetMemorySizeFromString(const std::wstring& input, const std::wstring& argName) { auto parsed = wsl::shared::string::ParseMemorySize(input.c_str()); if (!parsed.has_value()) @@ -256,7 +256,7 @@ ULONGLONG GetMemorySizeFromString(const std::wstring& input, const std::wstring& throw ArgumentException(Localization::WSLCCLI_InvalidMemorySizeError(argName, input)); } - return parsed.value(); + return static_cast(parsed.value()); } } // namespace wsl::windows::wslc::validation diff --git a/src/windows/wslc/arguments/ArgumentValidation.h b/src/windows/wslc/arguments/ArgumentValidation.h index 03665f595..e0d66fb58 100644 --- a/src/windows/wslc/arguments/ArgumentValidation.h +++ b/src/windows/wslc/arguments/ArgumentValidation.h @@ -63,7 +63,7 @@ void ValidateWSLCSignalFromString(const std::vector& values, const WSLCSignal GetWSLCSignalFromString(const std::wstring& input, const std::wstring& argName = {}); void ValidateMemorySize(const std::vector& values, const std::wstring& argName); -ULONGLONG GetMemorySizeFromString(const std::wstring& input, const std::wstring& argName = {}); +int64_t GetMemorySizeFromString(const std::wstring& input, const std::wstring& argName = {}); void ValidateFormatTypeFromString(const std::vector& values, const std::wstring& argName); FormatType GetFormatTypeFromString(const std::wstring& input, const std::wstring& argName = {}); diff --git a/src/windows/wslc/services/ContainerModel.h b/src/windows/wslc/services/ContainerModel.h index 88dc88a43..47e052788 100644 --- a/src/windows/wslc/services/ContainerModel.h +++ b/src/windows/wslc/services/ContainerModel.h @@ -38,7 +38,7 @@ struct ContainerOptions bool TTY = false; bool PublishAll = false; WSLCSignal StopSignal = WSLCSignalNone; - std::optional ShmSize{}; + std::optional ShmSize{}; bool Gpu = false; std::vector Ports; std::vector Volumes; diff --git a/src/windows/wslc/services/ImageModel.h b/src/windows/wslc/services/ImageModel.h index 1ebb87d03..a32d665b4 100644 --- a/src/windows/wslc/services/ImageModel.h +++ b/src/windows/wslc/services/ImageModel.h @@ -23,7 +23,7 @@ struct ImageInformation std::optional Tag; std::string Id; LONGLONG Created{}; - ULONGLONG Size{}; + int64_t Size{}; NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(ImageInformation, Repository, Tag, Id, Created, Size); }; diff --git a/src/windows/wslcsession/WSLCContainer.cpp b/src/windows/wslcsession/WSLCContainer.cpp index aaa602b00..08d9536ec 100644 --- a/src/windows/wslcsession/WSLCContainer.cpp +++ b/src/windows/wslcsession/WSLCContainer.cpp @@ -1413,10 +1413,7 @@ std::unique_ptr WSLCContainerImpl::Create( request.HostConfig.Ulimits = std::move(ulimits); } - if (containerOptions.ShmSize > 0) - { - request.HostConfig.ShmSize = containerOptions.ShmSize; - } + request.HostConfig.ShmSize = containerOptions.ShmSize; if (containerOptions.VolumesCount > 0) {