@samitouri / QOSAMI-WSL / commits / c12e3c03

CLI: Initialize shm-size and configure stop-signal (#40385)

* Init retarget * Fix build * Added tests * Update resw string * Potential fix for pull request finding Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> * Clang format * Resolve copilot comment * Apply suggestion from @AmelBawa-msft * Address PR comments: use pre-configured stop-signal and remove SignalArgDescription from non-en-US resw files Agent-Logs-Url: https://github.com/microsoft/WSL/sessions/18b17574-a958-4927-8ce9-10f3a054a4e7 Co-authored-by: AmelBawa-msft <104940545+AmelBawa-msft@users.noreply.github.com> * Revert "Address PR comments: use pre-configured stop-signal and remove SignalArgDescription from non-en-US resw files" This reverts commit 66e27600f2fa6459f20dc09866432961e118eaed. * Fix StopSignal type to WSLCSignal in metadata struct per code review Agent-Logs-Url: https://github.com/microsoft/WSL/sessions/18b17574-a958-4927-8ce9-10f3a054a4e7 Co-authored-by: AmelBawa-msft <104940545+AmelBawa-msft@users.noreply.github.com> * Update strings --------- Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>

AmirMS committed May 6, 2026 at 10:50 UTC c12e3c03d4e1a47ffee541b694d887e44f0a82ae
40 files changed +244 -99
localization/strings/cs-CZ/Resources.resw
-4
@@ -2636,10 +2636,6 @@ Při prvním spuštění vytvoří soubor se všemi nastaveními okomentovanými
2636 <data name="WSLCCLI_SessionStoragePositionalArgDescription" xml:space="preserve">
2637 <value>Cesta k úložišti relace</value>
2638 </data>
2639 - <data name="WSLCCLI_SignalArgDescription" xml:space="preserve">
2640 - <value>Signál k odeslání (výchozí: {})</value>
2641 - <comment>{FixedPlaceholder="{}"}Command line arguments, file names and string inserts should not be translated</comment>
2642 - </data>
2639 <data name="WSLCCLI_SourceArgDescription" xml:space="preserve">
2640 <value>Aktuální nebo existující odkaz na obrázek ve formátu image-name[:tag]</value>
2641 </data>
localization/strings/da-DK/Resources.resw
-4
@@ -2636,10 +2636,6 @@ Ved første kørsel oprettes filen med alle indstillinger kommenteret som standa
2636 <data name="WSLCCLI_SessionStoragePositionalArgDescription" xml:space="preserve">
2637 <value>Sti til sessionslager</value>
2638 </data>
2639 - <data name="WSLCCLI_SignalArgDescription" xml:space="preserve">
2640 - <value>Signal, der skal sendes (standard: {})</value>
2641 - <comment>{FixedPlaceholder="{}"}Command line arguments, file names and string inserts should not be translated</comment>
2642 - </data>
2639 <data name="WSLCCLI_SourceArgDescription" xml:space="preserve">
2640 <value>Aktuel eller eksisterende billedreference i formatet image-name[:tag]</value>
2641 </data>
localization/strings/de-DE/Resources.resw
-4
@@ -2642,10 +2642,6 @@ Erstellt bei der ersten Ausführung die Datei mit allen Einstellungen, die stand
2642 <data name="WSLCCLI_SessionStoragePositionalArgDescription" xml:space="preserve">
2643 <value>Pfad für den Sitzungsspeicher</value>
2644 </data>
2645 - <data name="WSLCCLI_SignalArgDescription" xml:space="preserve">
2646 - <value>Signal zum Senden (Standard: {})</value>
2647 - <comment>{FixedPlaceholder="{}"}Command line arguments, file names and string inserts should not be translated</comment>
2648 - </data>
2645 <data name="WSLCCLI_SourceArgDescription" xml:space="preserve">
2646 <value>Aktuelle oder vorhandene Bildreferenz im Format image-name[:tag]</value>
2647 </data>
localization/strings/en-GB/Resources.resw
-4
@@ -2636,10 +2636,6 @@ On first run, creates the file with all settings commented out at their defaults
2636 <data name="WSLCCLI_SessionStoragePositionalArgDescription" xml:space="preserve">
2637 <value>Session storage path</value>
2638 </data>
2639 - <data name="WSLCCLI_SignalArgDescription" xml:space="preserve">
2640 - <value>Signal to send (default: {})</value>
2641 - <comment>{FixedPlaceholder="{}"}Command line arguments, file names and string inserts should not be translated</comment>
2642 - </data>
2639 <data name="WSLCCLI_SourceArgDescription" xml:space="preserve">
2640 <value>Current or existing image reference in the image-name[:tag] format</value>
2641 </data>
localization/strings/en-US/Resources.resw
+12 -2
@@ -2630,6 +2630,13 @@ On first run, creates the file with all settings commented out at their defaults
2630 <data name="WSLCCLI_RemoveArgDescription" xml:space="preserve">
2631 <value>Remove the container after it stops</value>
2632 </data>
2633 + <data name="WSLCCLI_StopSignalArgDescription" xml:space="preserve">
2634 + <value>Signal to stop the container</value>
2635 + </data>
2636 + <data name="WSLCCLI_ShmSizeArgDescription" xml:space="preserve">
2637 + <value>Size of /dev/shm (e.g. 64M, 1G)</value>
2638 + <comment>{Locked="/dev/shm"}Command line arguments should not be translated</comment>
2639 + </data>
2640 <data name="WSLCCLI_SessionIdPositionalArgDescription" xml:space="preserve">
2641 <value>Session ID</value>
2642 </data>
@@ -2637,8 +2644,7 @@ On first run, creates the file with all settings commented out at their defaults
2644 <value>Session storage path</value>
2645 </data>
2646 <data name="WSLCCLI_SignalArgDescription" xml:space="preserve">
2640 - <value>Signal to send (default: {})</value>
2641 - <comment>{FixedPlaceholder="{}"}Command line arguments, file names and string inserts should not be translated</comment>
2647 + <value>Signal to send</value>
2648 </data>
2649 <data name="WSLCCLI_SourceArgDescription" xml:space="preserve">
2650 <value>Current or existing image reference in the image-name[:tag] format</value>
@@ -2748,6 +2754,10 @@ On first run, creates the file with all settings commented out at their defaults
2754 <value>Invalid {} value: {} is out of valid range ({}-{}).</value>
2755 <comment>{FixedPlaceholder="{}"}Command line arguments, file names and string inserts should not be translated</comment>
2756 </data>
2757 + <data name="WSLCCLI_InvalidMemorySizeError" xml:space="preserve">
2758 + <value>Invalid {} argument value: '{}'. Expected a memory size (e.g. 256M, 1G)</value>
2759 + <comment>{FixedPlaceholder="{}"}Command line arguments, file names and string inserts should not be translated{Locked="256M"}{Locked="1G"}</comment>
2760 + </data>
2761 <data name="WSLCCLI_ImageNotFoundPulling" xml:space="preserve">
2762 <value>Image '{}' not found, pulling</value>
2763 <comment>{FixedPlaceholder="{}"}Command line arguments, file names and string inserts should not be translated</comment>
localization/strings/es-ES/Resources.resw
-4
@@ -2642,10 +2642,6 @@ En la primera ejecución, crea el archivo con todas las configuraciones comentad
2642 <data name="WSLCCLI_SessionStoragePositionalArgDescription" xml:space="preserve">
2643 <value>Ruta de almacenamiento de sesión</value>
2644 </data>
2645 - <data name="WSLCCLI_SignalArgDescription" xml:space="preserve">
2646 - <value>Señal para enviar (valor predeterminado: {})</value>
2647 - <comment>{FixedPlaceholder="{}"}Command line arguments, file names and string inserts should not be translated</comment>
2648 - </data>
2645 <data name="WSLCCLI_SourceArgDescription" xml:space="preserve">
2646 <value>Referencia de imagen actual o existente en formato nombre-de-imagen[:etiqueta]</value>
2647 </data>
localization/strings/fi-FI/Resources.resw
-4
@@ -2636,10 +2636,6 @@ Ensimmäisellä käynnistyskerralla luo tiedoston, jossa kaikki asetukset on kom
2636 <data name="WSLCCLI_SessionStoragePositionalArgDescription" xml:space="preserve">
2637 <value>Istunnon tallennuspolku</value>
2638 </data>
2639 - <data name="WSLCCLI_SignalArgDescription" xml:space="preserve">
2640 - <value>Lähetettävä signaali (oletus: {})</value>
2641 - <comment>{FixedPlaceholder="{}"}Command line arguments, file names and string inserts should not be translated</comment>
2642 - </data>
2639 <data name="WSLCCLI_SourceArgDescription" xml:space="preserve">
2640 <value>Nykyinen tai olemassa oleva kuvaviittaus muodossa image-name[:tag]</value>
2641 </data>
localization/strings/fr-FR/Resources.resw
-4
@@ -2643,10 +2643,6 @@ Lors de la première exécution, crée le fichier avec tous les paramètres comm
2643 <data name="WSLCCLI_SessionStoragePositionalArgDescription" xml:space="preserve">
2644 <value>Chemin d’accès de stockage de session</value>
2645 </data>
2646 - <data name="WSLCCLI_SignalArgDescription" xml:space="preserve">
2647 - <value>Signal à envoyer (par défaut : {})</value>
2648 - <comment>{FixedPlaceholder="{}"}Command line arguments, file names and string inserts should not be translated</comment>
2649 - </data>
2646 <data name="WSLCCLI_SourceArgDescription" xml:space="preserve">
2647 <value>Référence d’image actuelle ou existante au format nom_image[ :tag]</value>
2648 </data>
localization/strings/hu-HU/Resources.resw
-4
@@ -2636,10 +2636,6 @@ Első futtatáskor a program létrehozza a fájlt, amelyben az összes beállít
2636 <data name="WSLCCLI_SessionStoragePositionalArgDescription" xml:space="preserve">
2637 <value>Munkamenet-tároló útvonala</value>
2638 </data>
2639 - <data name="WSLCCLI_SignalArgDescription" xml:space="preserve">
2640 - <value>Küldendő jel (alapértelmezett: {})</value>
2641 - <comment>{FixedPlaceholder="{}"}Command line arguments, file names and string inserts should not be translated</comment>
2642 - </data>
2639 <data name="WSLCCLI_SourceArgDescription" xml:space="preserve">
2640 <value>Jelenlegi vagy meglévő lemezkép-hivatkozás image-name[:tag] formátumban</value>
2641 </data>
localization/strings/it-IT/Resources.resw
-4
@@ -2642,10 +2642,6 @@ Alla prima esecuzione crea il file con tutte le impostazioni commentate come pre
2642 <data name="WSLCCLI_SessionStoragePositionalArgDescription" xml:space="preserve">
2643 <value>Percorso di archiviazione sessione</value>
2644 </data>
2645 - <data name="WSLCCLI_SignalArgDescription" xml:space="preserve">
2646 - <value>Segnale da inviare (impostazione predefinita: {})</value>
2647 - <comment>{FixedPlaceholder="{}"}Command line arguments, file names and string inserts should not be translated</comment>
2648 - </data>
2645 <data name="WSLCCLI_SourceArgDescription" xml:space="preserve">
2646 <value>Riferimento all'immagine corrente o esistente nel formato nome-immagine[:tag]</value>
2647 </data>
localization/strings/ja-JP/Resources.resw
-4
@@ -2642,10 +2642,6 @@ VS Code 自体のコマンド パレットから、より多くの VS Code リ
2642 <data name="WSLCCLI_SessionStoragePositionalArgDescription" xml:space="preserve">
2643 <value>セッション ストレージ パス</value>
2644 </data>
2645 - <data name="WSLCCLI_SignalArgDescription" xml:space="preserve">
2646 - <value>送信するシグナル (既定値: {})</value>
2647 - <comment>{FixedPlaceholder="{}"}Command line arguments, file names and string inserts should not be translated</comment>
2648 - </data>
2645 <data name="WSLCCLI_SourceArgDescription" xml:space="preserve">
2646 <value>image-name[:tag] 形式の現在または既存のイメージ参照</value>
2647 </data>
localization/strings/ko-KR/Resources.resw
-4
@@ -2642,10 +2642,6 @@ VS Code 자체 내의 명령 팔레트를 통해 더 많은 VS Code 원격 옵
2642 <data name="WSLCCLI_SessionStoragePositionalArgDescription" xml:space="preserve">
2643 <value>세션 저장소 경로</value>
2644 </data>
2645 - <data name="WSLCCLI_SignalArgDescription" xml:space="preserve">
2646 - <value>보낼 신호(기본값: {})</value>
2647 - <comment>{FixedPlaceholder="{}"}Command line arguments, file names and string inserts should not be translated</comment>
2648 - </data>
2645 <data name="WSLCCLI_SourceArgDescription" xml:space="preserve">
2646 <value>image-name[:tag] 형식의 현재 또는 기존 이미지 참조</value>
2647 </data>
localization/strings/nb-NO/Resources.resw
-4
@@ -2636,10 +2636,6 @@ Ved første kjøring opprettes filen med alle innstillinger kommentert ut som st
2636 <data name="WSLCCLI_SessionStoragePositionalArgDescription" xml:space="preserve">
2637 <value>Bane for øktlagring</value>
2638 </data>
2639 - <data name="WSLCCLI_SignalArgDescription" xml:space="preserve">
2640 - <value>Signal som skal sendes (standard: {})</value>
2641 - <comment>{FixedPlaceholder="{}"}Command line arguments, file names and string inserts should not be translated</comment>
2642 - </data>
2639 <data name="WSLCCLI_SourceArgDescription" xml:space="preserve">
2640 <value>Gjeldende eller eksisterende bildereferanse i bilde-navn[:merke]-format</value>
2641 </data>
localization/strings/nl-NL/Resources.resw
-4
@@ -2636,10 +2636,6 @@ Bij de eerste uitvoering wordt het bestand aangemaakt met alle instellingen geco
2636 <data name="WSLCCLI_SessionStoragePositionalArgDescription" xml:space="preserve">
2637 <value>Pad naar sessieopslag</value>
2638 </data>
2639 - <data name="WSLCCLI_SignalArgDescription" xml:space="preserve">
2640 - <value>Signaal om te verzenden (standaard: {})</value>
2641 - <comment>{FixedPlaceholder="{}"}Command line arguments, file names and string inserts should not be translated</comment>
2642 - </data>
2639 <data name="WSLCCLI_SourceArgDescription" xml:space="preserve">
2640 <value>Huidige of bestaande afbeeldingsverwijzing in de indeling voor de afbeeldingsnaam [:tag]</value>
2641 </data>
localization/strings/pl-PL/Resources.resw
-4
@@ -2636,10 +2636,6 @@ Przy pierwszym uruchomieniu tworzy plik ze wszystkimi ustawieniami ujętymi w ko
2636 <data name="WSLCCLI_SessionStoragePositionalArgDescription" xml:space="preserve">
2637 <value>Ścieżka magazynu sesji</value>
2638 </data>
2639 - <data name="WSLCCLI_SignalArgDescription" xml:space="preserve">
2640 - <value>Sygnał do wysłania (domyślnie: {})</value>
2641 - <comment>{FixedPlaceholder="{}"}Command line arguments, file names and string inserts should not be translated</comment>
2642 - </data>
2639 <data name="WSLCCLI_SourceArgDescription" xml:space="preserve">
2640 <value>Bieżące lub istniejące odwołanie do obrazu w formacie nazwa_obrazu[:tag]</value>
2641 </data>
localization/strings/pt-BR/Resources.resw
-4
@@ -2643,10 +2643,6 @@ Na primeira execução, cria o arquivo com todas as configurações comentadas n
2643 <data name="WSLCCLI_SessionStoragePositionalArgDescription" xml:space="preserve">
2644 <value>Caminho de armazenamento da sessão</value>
2645 </data>
2646 - <data name="WSLCCLI_SignalArgDescription" xml:space="preserve">
2647 - <value>Sinal a enviar (padrão: {})</value>
2648 - <comment>{FixedPlaceholder="{}"}Command line arguments, file names and string inserts should not be translated</comment>
2649 - </data>
2646 <data name="WSLCCLI_SourceArgDescription" xml:space="preserve">
2647 <value>Referência de imagem atual ou existente no formato image-name[:tag]</value>
2648 </data>
localization/strings/pt-PT/Resources.resw
-4
@@ -2636,10 +2636,6 @@ Na primeira execução, cria o ficheiro com todas as definições comentadas nas
2636 <data name="WSLCCLI_SessionStoragePositionalArgDescription" xml:space="preserve">
2637 <value>Caminho para armazenamento da sessão</value>
2638 </data>
2639 - <data name="WSLCCLI_SignalArgDescription" xml:space="preserve">
2640 - <value>Sinal a enviar (predefinição: {})</value>
2641 - <comment>{FixedPlaceholder="{}"}Command line arguments, file names and string inserts should not be translated</comment>
2642 - </data>
2639 <data name="WSLCCLI_SourceArgDescription" xml:space="preserve">
2640 <value>Referência de imagem atual ou existente no formato image-name[:tag]</value>
2641 </data>
localization/strings/ru-RU/Resources.resw
-4
@@ -2643,10 +2643,6 @@ wsl.exe --manage &lt;DistributionName&gt; --set-sparse true --allow-unsafe</valu
2643 <data name="WSLCCLI_SessionStoragePositionalArgDescription" xml:space="preserve">
2644 <value>Путь к хранилищу сеанса</value>
2645 </data>
2646 - <data name="WSLCCLI_SignalArgDescription" xml:space="preserve">
2647 - <value>Сигнал для отправки (по умолчанию: {})</value>
2648 - <comment>{FixedPlaceholder="{}"}Command line arguments, file names and string inserts should not be translated</comment>
2649 - </data>
2646 <data name="WSLCCLI_SourceArgDescription" xml:space="preserve">
2647 <value>Текущая или существующая ссылка на изображение в формате image-name[:tag]</value>
2648 </data>
localization/strings/sv-SE/Resources.resw
-4
@@ -2636,10 +2636,6 @@ Vid den första körningen skapas filen med alla inställningar kommenterade som
2636 <data name="WSLCCLI_SessionStoragePositionalArgDescription" xml:space="preserve">
2637 <value>Sökväg för sessionslagring</value>
2638 </data>
2639 - <data name="WSLCCLI_SignalArgDescription" xml:space="preserve">
2640 - <value>Signal att skicka (standard: {})</value>
2641 - <comment>{FixedPlaceholder="{}"}Command line arguments, file names and string inserts should not be translated</comment>
2642 - </data>
2639 <data name="WSLCCLI_SourceArgDescription" xml:space="preserve">
2640 <value>Aktuell eller befintlig bildreferens i formatet image-name[:tag]</value>
2641 </data>
localization/strings/tr-TR/Resources.resw
-4
@@ -2636,10 +2636,6 @@ Bu ürünle ilgili gizlilik bilgileri için lütfen https://aka.ms/privacy sayfa
2636 <data name="WSLCCLI_SessionStoragePositionalArgDescription" xml:space="preserve">
2637 <value>Oturum depolama alanı yolu</value>
2638 </data>
2639 - <data name="WSLCCLI_SignalArgDescription" xml:space="preserve">
2640 - <value>Gönderilecek sinyal (varsayılan: {})</value>
2641 - <comment>{FixedPlaceholder="{}"}Command line arguments, file names and string inserts should not be translated</comment>
2642 - </data>
2639 <data name="WSLCCLI_SourceArgDescription" xml:space="preserve">
2640 <value>image-name[:tag] biçiminde geçerli veya mevcut resim referansı</value>
2641 </data>
localization/strings/zh-CN/Resources.resw
-4
@@ -2642,10 +2642,6 @@ wsl.exe --manage &lt;DistributionName&gt; --set-sparse true --allow-unsafe</valu
2642 <data name="WSLCCLI_SessionStoragePositionalArgDescription" xml:space="preserve">
2643 <value>会话存储路径</value>
2644 </data>
2645 - <data name="WSLCCLI_SignalArgDescription" xml:space="preserve">
2646 - <value>要发送的信号(默认: {})</value>
2647 - <comment>{FixedPlaceholder="{}"}Command line arguments, file names and string inserts should not be translated</comment>
2648 - </data>
2645 <data name="WSLCCLI_SourceArgDescription" xml:space="preserve">
2646 <value>当前或现有图像引用采用 image-name[:tag] 格式</value>
2647 </data>
localization/strings/zh-TW/Resources.resw
-4
@@ -2642,10 +2642,6 @@ wsl.exe --manage &lt;DistributionName&gt; --set-sparse true --allow-unsafe</valu
2642 <data name="WSLCCLI_SessionStoragePositionalArgDescription" xml:space="preserve">
2643 <value>工作階段儲存路徑</value>
2644 </data>
2645 - <data name="WSLCCLI_SignalArgDescription" xml:space="preserve">
2646 - <value>要傳送的訊號 (預設: {})</value>
2647 - <comment>{FixedPlaceholder="{}"}Command line arguments, file names and string inserts should not be translated</comment>
2648 - </data>
2645 <data name="WSLCCLI_SourceArgDescription" xml:space="preserve">
2646 <value>目前或現有的影像參考採用影像名稱[:tag]格式</value>
2647 </data>
src/windows/common/WSLCContainerLauncher.cpp
+7 -1
@@ -129,6 +129,11 @@ void WSLCContainerLauncher::SetDefaultStopSignal(WSLCSignal Signal)
129 m_stopSignal = Signal;
130 }
131
132 +void WSLCContainerLauncher::SetShmSize(ULONGLONG ShmSize)
133 +{
134 + m_shmSize = ShmSize;
135 +}
136 +
137 void WSLCContainerLauncher::SetEntrypoint(std::vector<std::string>&& entrypoint)
138 {
139 m_entrypoint = std::move(entrypoint);
@@ -260,6 +265,7 @@ std::pair<HRESULT, std::optional<RunningWSLCContainer>> WSLCContainerLauncher::C
265 options.PortsCount = static_cast<ULONG>(m_ports.size());
266 options.StopSignal = m_stopSignal;
267 options.Flags = m_containerFlags;
268 + options.ShmSize = m_shmSize;
269
270 if (!entrypointStorage.empty())
271 {
@@ -326,7 +332,7 @@ std::pair<HRESULT, std::optional<RunningWSLCContainer>> WSLCContainerLauncher::C
332 options.TmpfsCount = static_cast<ULONG>(m_tmpfsMounts.size());
333 options.Tmpfs = m_tmpfsMounts.size() > 0 ? m_tmpfsMounts.data() : nullptr;
334
329 - // TODO: Support volumes, ports, flags, shm size, container networking mode, etc.
335 + // TODO: Support volumes, ports, flags, container networking mode, etc.
336 wil::com_ptr<IWSLCContainer> container;
337 auto result = Session.CreateContainer(&options, &container);
338 if (FAILED(result))
src/windows/common/WSLCContainerLauncher.h
+3 -1
@@ -72,6 +72,7 @@ public:
72 void SetName(std::string&& Name);
73 void SetEntrypoint(std::vector<std::string>&& entrypoint);
74 void SetDefaultStopSignal(WSLCSignal Signal);
75 + void SetShmSize(ULONGLONG ShmSize);
76 void SetContainerFlags(WSLCContainerFlags Flags);
77 void SetContainerNetworkName(std::string&& Name);
78 void SetHostname(std::string&& Hostname);
@@ -97,6 +98,7 @@ private:
98 std::string m_containerNetworkName;
99 std::vector<std::string> m_entrypoint;
100 WSLCSignal m_stopSignal = WSLCSignalNone;
101 + ULONGLONG m_shmSize = 0;
102 WSLCContainerFlags m_containerFlags = WSLCContainerFlagsNone;
103 std::string m_hostname;
104 std::string m_domainname;
@@ -110,4 +112,4 @@ private:
112 std::deque<std::string> m_tmpfsContainerPaths;
113 std::deque<std::string> m_tmpfsOptions;
114 };
113 -} // namespace wsl::windows::common
\ No newline at end of file
115 +} // namespace wsl::windows::common
src/windows/inc/docker_schema.h
+3 -1
@@ -214,9 +214,11 @@ struct HostConfig
214 std::optional<std::vector<std::string>> DnsOptions;
215 std::optional<std::vector<std::string>> Binds;
216 std::map<std::string, std::string> Tmpfs;
217 + std::optional<ULONGLONG> ShmSize;
218 std::optional<std::vector<DeviceMapping>> Devices;
219
219 - NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(HostConfig, Mounts, PortBindings, NetworkMode, Init, Dns, DnsSearch, DnsOptions, Binds, Tmpfs, Devices);
220 + NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(
221 + HostConfig, Mounts, PortBindings, NetworkMode, Init, Dns, DnsSearch, DnsOptions, Binds, Tmpfs, Devices, ShmSize);
222 };
223
224 struct CreateContainer
src/windows/wslc/arguments/ArgumentDefinitions.h
+3 -1
@@ -86,9 +86,11 @@ _(Remove, "rm", NO_ALIAS, Kind::Flag, L
86 _(Server, "server", NO_ALIAS, Kind::Positional, Localization::WSLCCLI_LoginServerArgDescription()) \
87 _(Session, "session", NO_ALIAS, Kind::Value, Localization::WSLCCLI_SessionIdArgDescription()) \
88 _(SessionId, "session-id", NO_ALIAS, Kind::Positional, Localization::WSLCCLI_SessionIdPositionalArgDescription()) \
89 +_(ShmSize, "shm-size", NO_ALIAS, Kind::Value, Localization::WSLCCLI_ShmSizeArgDescription()) \
90 _(StoragePath, "storage-path", NO_ALIAS, Kind::Positional, L"Path to the session storage directory") \
90 -_(Signal, "signal", L"s", Kind::Value, Localization::WSLCCLI_SignalArgDescription(L"SIGKILL")) \
91 +_(Signal, "signal", L"s", Kind::Value, Localization::WSLCCLI_SignalArgDescription()) \
92 _(Source, "source", NO_ALIAS, Kind::Positional, Localization::WSLCCLI_SourceArgDescription()) \
93 +_(StopSignal, "stop-signal", NO_ALIAS, Kind::Value, Localization::WSLCCLI_StopSignalArgDescription()) \
94 _(Tail, "tail", L"n", Kind::Value, Localization::WSLCCLI_TailArgDescription()) \
95 _(Tag, "tag", L"t", Kind::Value, Localization::WSLCCLI_TagArgDescription()) \
96 _(Target, "target", NO_ALIAS, Kind::Positional, Localization::WSLCCLI_TargetArgDescription()) \
src/windows/wslc/arguments/ArgumentValidation.cpp
+27
@@ -40,6 +40,14 @@ void Argument::Validate(const ArgMap& execArgs) const
40 validation::ValidateWSLCSignalFromString(execArgs.GetAll<ArgType::Signal>(), m_name);
41 break;
42
43 + case ArgType::StopSignal:
44 + validation::ValidateWSLCSignalFromString(execArgs.GetAll<ArgType::StopSignal>(), m_name);
45 + break;
46 +
47 + case ArgType::ShmSize:
48 + validation::ValidateMemorySize(execArgs.GetAll<ArgType::ShmSize>(), m_name);
49 + break;
50 +
51 case ArgType::Tail:
52 validation::ValidateIntegerFromString<ULONGLONG>(
53 execArgs.GetAll<ArgType::Tail>(), m_name, [](auto value) { return value != 0; });
@@ -211,4 +219,23 @@ void ValidateGpus(const std::vector<std::wstring>& values, const std::wstring& a
219 }
220 }
221
222 +void ValidateMemorySize(const std::vector<std::wstring>& values, const std::wstring& argName)
223 +{
224 + for (const auto& value : values)
225 + {
226 + std::ignore = GetMemorySizeFromString(value, argName);
227 + }
228 +}
229 +
230 +ULONGLONG GetMemorySizeFromString(const std::wstring& input, const std::wstring& argName)
231 +{
232 + auto parsed = wsl::shared::string::ParseMemorySize(input.c_str());
233 + if (!parsed.has_value())
234 + {
235 + throw ArgumentException(Localization::WSLCCLI_InvalidMemorySizeError(argName, input));
236 + }
237 +
238 + return parsed.value();
239 +}
240 +
241 } // namespace wsl::windows::wslc::validation
src/windows/wslc/arguments/ArgumentValidation.h
+3
@@ -62,6 +62,9 @@ T GetIntegerFromString(
62 void ValidateWSLCSignalFromString(const std::vector<std::wstring>& values, const std::wstring& argName);
63 WSLCSignal GetWSLCSignalFromString(const std::wstring& input, const std::wstring& argName = {});
64
65 +void ValidateMemorySize(const std::vector<std::wstring>& values, const std::wstring& argName);
66 +ULONGLONG GetMemorySizeFromString(const std::wstring& input, const std::wstring& argName = {});
67 +
68 void ValidateFormatTypeFromString(const std::vector<std::wstring>& values, const std::wstring& argName);
69 FormatType GetFormatTypeFromString(const std::wstring& input, const std::wstring& argName = {});
70
src/windows/wslc/commands/ContainerCreateCommand.cpp
+3 -1
@@ -53,6 +53,8 @@ std::vector<Argument> ContainerCreateCommand::GetArguments() const
53 Argument::Create(ArgType::Remove),
54 // Argument::Create(ArgType::Scheme),
55 Argument::Create(ArgType::Session),
56 + Argument::Create(ArgType::ShmSize),
57 + Argument::Create(ArgType::StopSignal),
58 Argument::Create(ArgType::TMPFS, false, NO_LIMIT),
59 Argument::Create(ArgType::TTY),
60 Argument::Create(ArgType::User),
@@ -82,4 +84,4 @@ void ContainerCreateCommand::ExecuteInternal(CLIExecutionContext& context) const
84 << CreateContainer;
85 }
86 // clang-format on
85 -} // namespace wsl::windows::wslc
\ No newline at end of file
87 +} // namespace wsl::windows::wslc
src/windows/wslc/commands/ContainerRunCommand.cpp
+2
@@ -54,6 +54,8 @@ std::vector<Argument> ContainerRunCommand::GetArguments() const
54 Argument::Create(ArgType::Remove),
55 // Argument::Create(ArgType::Scheme),
56 Argument::Create(ArgType::Session),
57 + Argument::Create(ArgType::ShmSize),
58 + Argument::Create(ArgType::StopSignal),
59 Argument::Create(ArgType::TMPFS, false, NO_LIMIT),
60 Argument::Create(ArgType::TTY),
61 Argument::Create(ArgType::User),
src/windows/wslc/commands/ContainerStopCommand.cpp
+2 -2
@@ -29,7 +29,7 @@ std::vector<Argument> ContainerStopCommand::GetArguments() const
29 return {
30 Argument::Create(ArgType::ContainerId, std::nullopt, NO_LIMIT),
31 Argument::Create(ArgType::Session),
32 - Argument::Create(ArgType::Signal, std::nullopt, std::nullopt, Localization::WSLCCLI_SignalArgDescription(L"SIGTERM")),
32 + Argument::Create(ArgType::Signal),
33 Argument::Create(ArgType::Time),
34 };
35 }
@@ -52,4 +52,4 @@ void ContainerStopCommand::ExecuteInternal(CLIExecutionContext& context) const
52 << StopContainers;
53 }
54 // clang-format on
55 -} // namespace wsl::windows::wslc
\ No newline at end of file
55 +} // namespace wsl::windows::wslc
src/windows/wslc/services/ContainerModel.h
+3 -1
@@ -37,6 +37,8 @@ struct ContainerOptions
37 bool Remove = false;
38 bool TTY = false;
39 bool PublishAll = false;
40 + WSLCSignal StopSignal = WSLCSignalNone;
41 + std::optional<ULONGLONG> ShmSize{};
42 bool Gpu = false;
43 std::vector<std::string> Ports;
44 std::vector<std::wstring> Volumes;
@@ -61,7 +63,7 @@ struct StopContainerOptions
63 {
64 static constexpr LONG DefaultTimeout = -1;
65
64 - WSLCSignal Signal = WSLCSignalSIGTERM;
66 + WSLCSignal Signal = WSLCSignalNone;
67 LONG Timeout = DefaultTimeout;
68 };
69
src/windows/wslc/services/ContainerService.cpp
+10
@@ -96,6 +96,16 @@ static wsl::windows::common::RunningWSLCContainer CreateInternal(Session& sessio
96
97 containerLauncher.SetContainerFlags(containerFlags);
98
99 + if (options.StopSignal != WSLCSignalNone)
100 + {
101 + containerLauncher.SetDefaultStopSignal(options.StopSignal);
102 + }
103 +
104 + if (options.ShmSize.has_value())
105 + {
106 + containerLauncher.SetShmSize(options.ShmSize.value());
107 + }
108 +
109 if (!options.Entrypoint.empty())
110 {
111 auto entrypoints = options.Entrypoint;
src/windows/wslc/tasks/ContainerTasks.cpp
+10
@@ -281,6 +281,16 @@ void SetContainerOptionsFromArgs(CLIExecutionContext& context)
281 options.Remove = true;
282 }
283
284 + if (context.Args.Contains(ArgType::StopSignal))
285 + {
286 + options.StopSignal = validation::GetWSLCSignalFromString(context.Args.Get<ArgType::StopSignal>());
287 + }
288 +
289 + if (context.Args.Contains(ArgType::ShmSize))
290 + {
291 + options.ShmSize = validation::GetMemorySizeFromString(context.Args.Get<ArgType::ShmSize>());
292 + }
293 +
294 if (context.Args.Contains(ArgType::Command))
295 {
296 options.Arguments.emplace_back(WideToMultiByte(context.Args.Get<ArgType::Command>()));
src/windows/wslcsession/WSLCContainer.cpp
+5
@@ -1300,6 +1300,11 @@ std::unique_ptr<WSLCContainerImpl> WSLCContainerImpl::Create(
1300
1301 request.HostConfig.Init = WI_IsFlagSet(containerOptions.Flags, WSLCContainerFlagsInit);
1302
1303 + if (containerOptions.ShmSize > 0)
1304 + {
1305 + request.HostConfig.ShmSize = containerOptions.ShmSize;
1306 + }
1307 +
1308 if (containerOptions.VolumesCount > 0)
1309 {
1310 THROW_HR_IF_NULL_MSG(E_INVALIDARG, containerOptions.Volumes, "Volumes is null with VolumesCount=%lu", containerOptions.VolumesCount);
src/windows/wslcsession/WSLCContainerMetadata.h
+1 -1
@@ -67,4 +67,4 @@ struct WSLCContainerMetadata
67 NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(WSLCContainerMetadata, V1);
68 };
69
70 -} // namespace wsl::windows::service::wslc
\ No newline at end of file
70 +} // namespace wsl::windows::service::wslc
test/windows/wslc/e2e/WSLCE2EContainerCreateTests.cpp
+78
@@ -662,6 +662,82 @@ class WSLCE2EContainerCreateTests
662 VERIFY_IS_TRUE(result.Stdout->find(L"options ndots:5 timeout:3") != std::wstring::npos);
663 }
664
665 + WSLC_TEST_METHOD(WSLCE2E_Container_Create_StopSignal)
666 + {
667 + constexpr int ExpectedExitCode = 42;
668 + auto result = RunWslc(std::format(
669 + LR"(container create --stop-signal SIGUSR1 --name {} {} bash -c "trap 'exit {}' SIGUSR1; while true; do sleep 1; done")",
670 + WslcContainerName,
671 + DebianImage.NameAndTag(),
672 + ExpectedExitCode));
673 + result.Verify({.Stderr = L"", .ExitCode = 0});
674 + const auto containerId = result.GetStdoutOneLine();
675 + VerifyContainerIsListed(containerId, L"created");
676 +
677 + result = RunWslc(std::format(L"container start {}", WslcContainerName));
678 + result.Verify({.Stderr = L"", .ExitCode = 0});
679 + VerifyContainerIsListed(containerId, L"running");
680 +
681 + result = RunWslc(std::format(L"container stop {}", WslcContainerName));
682 + result.Verify({.Stderr = L"", .ExitCode = 0});
683 +
684 + const auto inspect = InspectContainer(WslcContainerName);
685 + VERIFY_IS_FALSE(inspect.State.Running);
686 + VERIFY_ARE_EQUAL(ExpectedExitCode, inspect.State.ExitCode);
687 + }
688 +
689 + WSLC_TEST_METHOD(WSLCE2E_Container_Create_ShmSize)
690 + {
691 + auto result = RunWslc(
692 + std::format(L"container create --shm-size 128M --name {} {} df -h /dev/shm", WslcContainerName, DebianImage.NameAndTag()));
693 + result.Verify({.Stderr = L"", .ExitCode = 0});
694 +
695 + result = RunWslc(std::format(L"container start -a {}", WslcContainerName));
696 + result.Verify({.Stderr = L"", .ExitCode = 0});
697 + VERIFY_IS_TRUE(result.Stdout->find(L"128M") != std::wstring::npos);
698 + }
699 +
700 + WSLC_TEST_METHOD(WSLCE2E_Container_Create_ShmSize_Invalid)
701 + {
702 + {
703 + auto result =
704 + RunWslc(std::format(L"container create --shm-size invalid --name {} {}", WslcContainerName, DebianImage.NameAndTag()));
705 + result.Verify({.Stderr = L"Invalid shm-size argument value: 'invalid'. Expected a memory size (e.g. 256M, 1G)\r\n", .ExitCode = 1});
706 + VerifyContainerIsNotListed(WslcContainerName);
707 + }
708 +
709 + {
710 + auto result =
711 + RunWslc(std::format(L"container create --shm-size 128X --name {} {}", WslcContainerName, DebianImage.NameAndTag()));
712 + result.Verify({.Stderr = L"Invalid shm-size argument value: '128X'. Expected a memory size (e.g. 256M, 1G)\r\n", .ExitCode = 1});
713 + VerifyContainerIsNotListed(WslcContainerName);
714 + }
715 + }
716 +
717 + WSLC_TEST_METHOD(WSLCE2E_Container_Create_StopSignal_Invalid)
718 + {
719 + {
720 + auto result = RunWslc(
721 + std::format(L"container create --stop-signal SIGINVALID --name {} {}", WslcContainerName, DebianImage.NameAndTag()));
722 + result.Verify({.Stderr = L"Invalid stop-signal value: SIGINVALID is not a recognized signal name or number (Example: SIGKILL, kill, or 9).\r\n", .ExitCode = 1});
723 + VerifyContainerIsNotListed(WslcContainerName);
724 + }
725 +
726 + {
727 + auto result =
728 + RunWslc(std::format(L"container create --stop-signal 0 --name {} {}", WslcContainerName, DebianImage.NameAndTag()));
729 + result.Verify({.Stderr = L"Invalid stop-signal value: 0 is out of valid range (1-31).\r\n", .ExitCode = 1});
730 + VerifyContainerIsNotListed(WslcContainerName);
731 + }
732 +
733 + {
734 + auto result =
735 + RunWslc(std::format(L"container create --stop-signal 99 --name {} {}", WslcContainerName, DebianImage.NameAndTag()));
736 + result.Verify({.Stderr = L"Invalid stop-signal value: 99 is out of valid range (1-31).\r\n", .ExitCode = 1});
737 + VerifyContainerIsNotListed(WslcContainerName);
738 + }
739 + }
740 +
741 private:
742 // Test container name
743 const std::wstring WslcContainerName = L"wslc-test-container";
@@ -737,6 +813,8 @@ private:
813 << L" -P,--publish-all Publish all exposed ports to random host ports\r\n"
814 << L" --rm Remove the container after it stops\r\n"
815 << L" --session Specify the session to use\r\n"
816 + << L" --shm-size Size of /dev/shm (e.g. 64M, 1G)\r\n"
817 + << L" --stop-signal Signal to stop the container\r\n"
818 << L" --tmpfs Mount tmpfs to the container at the given path\r\n"
819 << L" -t,--tty Open a TTY with the container process.\r\n"
820 << L" -u,--user User ID for the process (name|uid|uid:gid)\r\n"
test/windows/wslc/e2e/WSLCE2EContainerKillTests.cpp
+2 -2
@@ -179,10 +179,10 @@ private:
179 std::wstringstream options;
180 options << L"The following options are available:\r\n"
181 << L" --session Specify the session to use\r\n"
182 - << L" -s,--signal Signal to send (default: SIGKILL)\r\n"
182 + << L" -s,--signal Signal to send\r\n"
183 << L" -?,--help Shows help about the selected command\r\n"
184 << L"\r\n";
185 return options.str();
186 }
187 };
188 -} // namespace WSLCE2ETests
\ No newline at end of file
188 +} // namespace WSLCE2ETests
test/windows/wslc/e2e/WSLCE2EContainerRunTests.cpp
+68
@@ -652,6 +652,72 @@ class WSLCE2EContainerRunTests
652 VERIFY_ARE_EQUAL("2", inspect.Labels["B"]);
653 }
654
655 + WSLC_TEST_METHOD(WSLCE2E_Container_Run_StopSignal)
656 + {
657 + constexpr int ExpectedExitCode = 42;
658 + auto result = RunWslc(std::format(
659 + LR"(container run -d --stop-signal SIGUSR1 --name {} {} bash -c "trap 'exit {}' SIGUSR1; while true; do sleep 1; done")",
660 + WslcContainerName,
661 + DebianImage.NameAndTag(),
662 + ExpectedExitCode));
663 + result.Verify({.Stderr = L"", .ExitCode = 0});
664 +
665 + result = RunWslc(std::format(L"container stop {}", WslcContainerName));
666 + result.Verify({.Stderr = L"", .ExitCode = 0});
667 +
668 + const auto inspect = InspectContainer(WslcContainerName);
669 + VERIFY_IS_FALSE(inspect.State.Running);
670 + VERIFY_ARE_EQUAL(ExpectedExitCode, inspect.State.ExitCode);
671 + }
672 +
673 + WSLC_TEST_METHOD(WSLCE2E_Container_Run_ShmSize)
674 + {
675 + auto result = RunWslc(std::format(L"container run --rm --shm-size 128M {} df -h /dev/shm", DebianImage.NameAndTag()));
676 + result.Verify({.Stderr = L"", .ExitCode = 0});
677 + VERIFY_IS_TRUE(result.Stdout->find(L"128M") != std::wstring::npos);
678 + }
679 +
680 + WSLC_TEST_METHOD(WSLCE2E_Container_Run_ShmSize_Invalid)
681 + {
682 + {
683 + auto result =
684 + RunWslc(std::format(L"container run --rm --shm-size invalid --name {} {}", WslcContainerName, DebianImage.NameAndTag()));
685 + result.Verify({.Stderr = L"Invalid shm-size argument value: 'invalid'. Expected a memory size (e.g. 256M, 1G)\r\n", .ExitCode = 1});
686 + EnsureContainerDoesNotExist(WslcContainerName);
687 + }
688 +
689 + {
690 + auto result =
691 + RunWslc(std::format(L"container run --rm --shm-size 128X --name {} {}", WslcContainerName, DebianImage.NameAndTag()));
692 + result.Verify({.Stderr = L"Invalid shm-size argument value: '128X'. Expected a memory size (e.g. 256M, 1G)\r\n", .ExitCode = 1});
693 + EnsureContainerDoesNotExist(WslcContainerName);
694 + }
695 + }
696 +
697 + WSLC_TEST_METHOD(WSLCE2E_Container_Run_StopSignal_Invalid)
698 + {
699 + {
700 + auto result = RunWslc(
701 + std::format(L"container run --rm --stop-signal SIGINVALID --name {} {}", WslcContainerName, DebianImage.NameAndTag()));
702 + result.Verify({.Stderr = L"Invalid stop-signal value: SIGINVALID is not a recognized signal name or number (Example: SIGKILL, kill, or 9).\r\n", .ExitCode = 1});
703 + EnsureContainerDoesNotExist(WslcContainerName);
704 + }
705 +
706 + {
707 + auto result =
708 + RunWslc(std::format(L"container run --rm --stop-signal 0 --name {} {}", WslcContainerName, DebianImage.NameAndTag()));
709 + result.Verify({.Stderr = L"Invalid stop-signal value: 0 is out of valid range (1-31).\r\n", .ExitCode = 1});
710 + EnsureContainerDoesNotExist(WslcContainerName);
711 + }
712 +
713 + {
714 + auto result =
715 + RunWslc(std::format(L"container run --rm --stop-signal 99 --name {} {}", WslcContainerName, DebianImage.NameAndTag()));
716 + result.Verify({.Stderr = L"Invalid stop-signal value: 99 is out of valid range (1-31).\r\n", .ExitCode = 1});
717 + EnsureContainerDoesNotExist(WslcContainerName);
718 + }
719 + }
720 +
721 private:
722 // Test container name
723 const std::wstring WslcContainerName = L"wslc-test-container";
@@ -733,6 +799,8 @@ private:
799 << L" -P,--publish-all Publish all exposed ports to random host ports\r\n"
800 << L" --rm Remove the container after it stops\r\n"
801 << L" --session Specify the session to use\r\n"
802 + << L" --shm-size Size of /dev/shm (e.g. 64M, 1G)\r\n"
803 + << L" --stop-signal Signal to stop the container\r\n"
804 << L" --tmpfs Mount tmpfs to the container at the given path\r\n"
805 << L" -t,--tty Open a TTY with the container process.\r\n"
806 << L" -u,--user User ID for the process (name|uid|uid:gid)\r\n"
test/windows/wslc/e2e/WSLCE2EContainerStopTests.cpp
+2 -2
@@ -294,11 +294,11 @@ private:
294 std::wstringstream options;
295 options << L"The following options are available:\r\n"
296 << L" --session Specify the session to use\r\n"
297 - << L" -s,--signal Signal to send (default: SIGTERM)\r\n"
297 + << L" -s,--signal Signal to send\r\n"
298 << L" -t,--time Time in seconds to wait before executing (default 5)\r\n"
299 << L" -?,--help Shows help about the selected command\r\n"
300 << L"\r\n";
301 return options.str();
302 }
303 };
304 -} // namespace WSLCE2ETests
\ No newline at end of file
304 +} // namespace WSLCE2ETests