Guest User

Trying to Debug Across Wine Linux

a guest
Jun 20th, 2026
15
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 25.00 KB | None | 0 0
  1. # Debugging s&box (Source 2 + CoreCLR/.NET 10) on Linux from a JetBrains Rider Workflow: A Complete Failure Report
  2.  
  3. *A knowledge dump for anyone who comes after. Last updated May 2026.*
  4.  
  5. ---
  6.  
  7. ## TL;DR
  8.  
  9. **You cannot, today, attach JetBrains Rider (native Linux build) to a managed s&box editor process running under Steam Proton/Wine and get C# breakpoints. This is structurally unsupported by both JetBrains and Microsoft, and is blocked by an unimplemented Wine API (`NtFsControlFile` named-pipe enumeration) that breaks every variant of the approach.**
  10.  
  11. What does work today, in order of effort:
  12.  
  13. 1. **dnSpy.exe inside the Wine prefix** — full managed debugging in dnSpy's own UI. ~15 minutes. EULA-clean. Easiest win.
  14. 2. **VS Code + Microsoft `vsdbg.exe` inside the Wine prefix**, driven via `pipeTransport` — full managed debugging in VS Code. ~1–2 hours setup. EULA-clean (vsdbg permits VS Code clients). Documented working since WineHQ Forum #34925 (Sept 2020).
  15. 3. **Rider for Windows installed inside the same Wine prefix as sbox-dev.exe** — gets you Rider's UI but, critically, **still fails at process detection** for the same Wine pipe-enumeration reason native Rider does. Dead end. Don't bother.
  16. 4. **Native LLDB attach from Rider** — works for unmanaged native debugging only. No C#. Useful for engine-level crashes, useless for gameplay code.
  17. 5. **Wait for Facepunch native Linux build** (sbox-issues #7428, opened Jan 2025) — would obsolete this entire problem. No ETA.
  18.  
  19. If you take only one thing from this document: **set up either dnSpy-in-Wine or VS Code + vsdbg-in-Wine and stop trying to make Rider work.**
  20.  
  21. ---
  22.  
  23. ## 1. Setup and goal
  24.  
  25. **Target environment** (this report, May 2026):
  26. - Fedora 43, kernel 6.19.13, ntsync available
  27. - Steam Proton 11.0
  28. - pressure-vessel / bubblewrap sandbox (Steam Linux Runtime 4)
  29. - s&box editor: `sbox-dev.exe`, hybrid Source 2 native + CoreCLR/.NET 10 (10.0.7 runtime in-prefix)
  30. - Native Linux JetBrains Rider 2026.1.1 (Toolbox install)
  31. - Wine prefix: `~/.local/share/Steam/steamapps/compatdata/<appid>/pfx/`
  32.  
  33. **Goal**: Set a breakpoint in a C# `.cs` file in Rider, trigger the code in-game, hit the breakpoint, inspect locals and call stack. The exact workflow that "just works" on Windows.
  34.  
  35. **On Windows**, the workflow is well-documented (Facepunch wiki: `wiki.facepunch.com/sbox/Setting_up_Rider`): Run → Attach to Process → `sbox-dev.exe`. With "Just My Code" off and "Require source files to exactly match" off, breakpoints in your addon code work immediately. No special configuration.
  36.  
  37. **On Linux via Proton, none of this works.** This report explains why, in detail.
  38.  
  39. ---
  40.  
  41. ## 2. The core architectural problem
  42.  
  43. ### 2.1 Why standard tools fail
  44.  
  45. CoreCLR exposes its debugger transport via OS-native IPC. On Windows it's named pipes (`\\.\pipe\dotnet-diagnostic-<pid>` and `\\.\pipe\clr-debug-pipe-...`). On Linux it's Unix domain sockets and FIFOs (`/tmp/dotnet-diagnostic-<pid>-<key>-socket`, `/tmp/clr-debug-pipe-<pid>-<disambig>-{in,out}`).
  46.  
  47. When CoreCLR runs **inside Wine**, it creates the **Windows-style** named pipes inside `wineserver`'s namespace. Linux tools looking in `/tmp/` for the Linux-style sockets find nothing. The pipes exist, but they're inside a different kernel-level namespace.
  48.  
  49. Worse: `wineserver` itself is contained inside the pressure-vessel/bubblewrap sandbox, so even if a tool could see Wine's pipes, it would need to enter the sandbox first via the Steam compat-launcher D-Bus service.
  50.  
  51. ### 2.2 The Wine bug that kills every JetBrains path
  52.  
  53. JetBrains' .NET process detection (`MsClrLocalAttachableHolder`, `ProcessEnumerator.Worker`, `CollectedProcessesAttachProviderBase`, and the SSH-deployed `jb-debug-ssh.exe` agent) all rely on enumerating named pipes via `NtFsControlFile` with the `FSCTL_PIPE_LIST_*` family of control codes. **Wine returns `STATUS_NOT_SUPPORTED` (Win32 error 50, "Request not supported") for these.**
  54.  
  55. Symptom in JetBrains worker logs:
  56. ```
  57. Win32Exception NativeErrorCode=50 "Request not supported"
  58. from NamedPipeUtils.GetNamedPipeNames
  59. ```
  60.  
  61. This means: even when Rider is *running inside Wine* in the same prefix as sbox-dev, it still cannot enumerate the diagnostic pipes that would tell it "this process is managed." sbox-dev gets classified as native, only LLDB is offered, no C# breakpoints possible.
  62.  
  63. ### 2.3 Why "diagnostic port" workarounds don't help debugging
  64.  
  65. A common suggestion is `DOTNET_DiagnosticPorts` to redirect CoreCLR's diagnostic IPC. This is a dead end for **debugging**:
  66.  
  67. - CoreCLR's **diagnostic port** (`DOTNET_IPC_V1` protocol) handles tracing (`dotnet-trace`), dumps (`dotnet-dump`), counters (`dotnet-counters`), profiler attach. It does **not** carry debugger commands.
  68. - CoreCLR's **debugger transport** (`clr-debug-pipe-*`) is a separate set of FIFOs/pipes. The two systems do not interoperate.
  69. - `DOTNET_DiagnosticPorts=tcp://...` is **not supported on CoreCLR Windows/Linux desktop**. TCP listen mode exists only in Mono on Android/iOS. Confirmed in dotnet/runtime issue #88177.
  70.  
  71. Bridging the diagnostic pipe with `winestreamproxy` or `outflow` lets you run `dotnet-trace` against the Wine-side game (genuinely useful for profiling). It does **nothing** for setting breakpoints.
  72.  
  73. ### 2.4 Why JetBrains and Microsoft can't fix this for you
  74.  
  75. - **JetBrains** wrote their own debugger backend (`JetBrains.Debugger.Worker.exe`, `RdProtocol` over TCP). They cannot ship Microsoft's `vsdbg.exe` because the vsdbg EULA explicitly limits use to "Visual Studio Code, Visual Studio or Visual Studio for Mac." See dotnet/core issue #4788, dotnet/core #505 (the historical removal of clrdbg).
  76. - **Microsoft's** `vsdbg.exe` works fine under Wine (confirmed by WineHQ Forum #34925) — but Rider can't legally drive it.
  77. - **Wine** could implement the pipe enumeration ioctls, which would unblock JetBrains tools entirely. This is the cleanest long-term fix and would benefit every .NET developer using Wine. No one has stepped up.
  78.  
  79. ---
  80.  
  81. ## 3. Every approach attempted (and how each one died)
  82.  
  83. This is the unfiltered list of dead ends. Read this so you don't waste days repeating them.
  84.  
  85. ### 3.1 Native Linux Rider — Local Attach
  86.  
  87. **Idea**: Just click Run → Attach to Process in native Linux Rider, like you would on Windows.
  88.  
  89. **Result**: sbox-dev appears in the list but is classified as **Native** with only LLDB as a debugger option. No .NET option.
  90.  
  91. **Why**: Rider's Linux-side enumerator scans `/proc/*/maps` for `libcoreclr.so` and `/tmp/dotnet-diagnostic-*` Unix sockets. Wine processes load `coreclr.dll` (PE), and CoreCLR-in-Wine puts its diagnostic pipes inside wineserver. Neither is visible to Rider's Linux-native enumerator.
  92.  
  93. ### 3.2 Native Linux Rider — Attach to Remote Process via SSH (`jb-debug-ssh.exe`)
  94.  
  95. **Idea**: Treat the Wine prefix as a "remote Windows host." Install JetBrains' SSH debug agent (`jb-debug-ssh.exe`) into the prefix, SSH to it from native Rider, let Rider's normal remote-attach pipeline take over.
  96.  
  97. **Steps actually taken**:
  98. - Built a wrapper script (`~/sbox-proton-run.sh`) using `steam-runtime-launch-client --bus-name=com.steampowered.App<appid> -- wine $@` to enter the pressure-vessel sandbox and the same wineserver as sbox-dev.
  99. - Required Steam launch options: `STEAM_COMPAT_LAUNCHER_SERVICE=proton %command%`.
  100. - Tried Win32-OpenSSH inside the Wine prefix on port 2222. Failed: every OpenSSH version (8.6, 8.9, 10.x) errors with `kex_exchange_identification: Connection reset` due to architectural incompatibility between OpenSSH's privsep model (`UsePrivilegeSeparation` removed since 7.5) and Wine's `lookup_sid()` returning 1332. `sshd-session.exe` dies before key exchange completes.
  101. - Pivoted to JetBrains' `jb-debug-ssh.exe` (downloaded from `https://download.jetbrains.com/rider/ssh-remote-debugging/windows-x64/`). Placed at `<prefix>/drive_c/JBAgent/jb-debug-ssh.exe`. Runs cleanly, prints Login/Password/Port. SSH from Linux works.
  102. - Verified `ProcessEnumerator.Worker.exe` was running real CoreCLR (not wine-mono) by checking `/proc/<wine_pid>/environ`.
  103. - Made permanent via registry: `HKCU\Software\Wine\DllOverrides\mscoree=""` (later reverted) and `HKCU\Environment\DOTNET_ROOT=C:\Program Files\dotnet`.
  104.  
  105. **Result**: ProcessEnumerator.Worker.exe dies during enumeration. Logs show:
  106. ```
  107. Win32Exception NativeErrorCode=50 "Request not supported"
  108. from NamedPipeUtils.GetNamedPipeNames
  109. ```
  110. Plus failure to load `C:\windows\Microsoft.NET\Framework64\v4.0.30319\wminet_utils.dll` (WMI is also a fallback detection path, also unavailable in Wine).
  111.  
  112. **Why it failed**: Wine doesn't implement pipe enumeration ioctls. Rider's enumerator has no way to find managed processes. It silently exits or returns "no managed processes found."
  113.  
  114. ### 3.3 Symlink/wrapper hack on `JetBrains.Debugger.Worker`
  115.  
  116. **Idea**: Replace Rider's Linux `JetBrains.Debugger.Worker` binary with a wrapper script that filters Linux-specific args and forwards the call to the Windows-side worker via the wine wrapper. If Rider invokes the worker, the wrapper translates and runs it under Wine.
  117.  
  118. **Result**: Wrapper script never gets called. `rider-wine-worker.log` always empty.
  119.  
  120. **Why it failed**: For Rider to invoke the .NET worker, it must first **classify the process as managed**. Classification fails (per 3.1/3.2), so Rider always picks LLDB native debugger. The .NET worker entry point is never reached, the wrapper is never executed.
  121.  
  122. **Lesson**: This was the most honest "stacked uncertainty" of the project — three things had to work, and the very first one (managed detection) was the same thing that had been failing all along. Don't try to wrap a code path that doesn't get exercised.
  123.  
  124. ### 3.4 Rider for Windows installed inside the Wine prefix ("Option 2")
  125.  
  126. **Idea**: If native Rider can't see across the Wine boundary, install Rider for Windows *inside* the Wine prefix. It would be in the same wineserver as sbox-dev, so the same Win32 detection mechanisms it uses on real Windows should work.
  127.  
  128. **Steps actually taken**:
  129. - Downloaded Rider 2026.1.1 Windows installer, ran via wrapper into the prefix.
  130. - Hit a JBR LCD antialiasing crash: `IllegalArgumentException: 0 incompatible with Text-specific LCD contrast key`. Wine's `WDesktopProperties.getDesktopAAHints` returns `0` which Java rejects. **Fix**: append `-Dawt.useSystemAAFontSettings=off` and `-Dswing.aatext=false` to `<prefix>/Program Files/JetBrains/JetBrains Rider 2026.1.1/bin/rider64.exe.vmoptions`.
  131. - Hit a crash on "Open Solution": `DE_ELEVATION_FAILURE (101)` (Rider daemon needs UAC, which Wine stubs) plus JVM crash `0xc06d007e STATUS_DELAY_LOAD_MODULE_NOT_FOUND` in kernelbase.dll. **Fix**: bypass solution-open and use Open Folder instead.
  132. - Hit a crash on "Open Folder": COM `IFileOpenDialog` fails because Wine's shell32 has gaps. **Fix**: pass the folder on the command line, bypassing the file picker entirely.
  133. - Hit "Cannot Execute Command — Unable to open file Z:\...": Rider's CLI processor couldn't open the path. **Fix**: create a symlink from `<prefix>/drive_c/sbox` → `/path/to/sbox-public`, then open via `C:\sbox\game`. Z:\ paths are theoretically fine but trip up Rider's path resolver.
  134. - Hit MSBuild `[MSB4237] DotNetMSBuildSdkResolver failed to load`. **Fix**: install .NET 10 SDK (Windows x64) into `<prefix>/drive_c/Program Files/dotnet/`. Runtime alone isn't enough; Rider needs the SDK to load `.csproj` files.
  135.  
  136. **Result after all fixes**: Rider opens the folder, project loads, attach dialog opens.
  137.  
  138. **But sbox-dev still shows as Native only.** Same root cause as 3.1/3.2: Wine's pipe enumeration is broken regardless of whether the enumerator runs on Linux or inside Wine. The same wineserver doesn't help if the API is unimplemented.
  139.  
  140. Trying to attach as Native gives `0xC0000135` (`STATUS_DLL_NOT_FOUND`) because LLDB.exe needs Win32 runtime DLLs not present in Wine. Fixable with `protontricks vcrun2022` but only enables native debugging which we don't want.
  141.  
  142. **Verdict**: Option 2 is structurally dead for the same reason. Significantly more setup for the same wall.
  143.  
  144. ### 3.5 Researched but not attempted (or attempted briefly and abandoned)
  145.  
  146. | Approach | Result | Why |
  147. |---|---|---|
  148. | `DOTNET_DiagnosticPorts=tcp://...` | Not supported on CoreCLR desktop | Mono mobile only; doesn't carry debugger commands anyway |
  149. | `winestreamproxy`/`outflow` pipe→socket bridge | Works for traces, not debugging | Bridges diagnostic IPC, not debugger transport |
  150. | Mono SDB protocol | Doesn't apply | CoreCLR doesn't speak SDB |
  151. | `msvsmon.exe` (VS Remote Debugger) under Wine | Rider doesn't speak msvsmon protocol | Dead end for Rider |
  152. | ICorProfiler hook | Not a debugger | Profilers can't set breakpoints |
  153. | Custom Rider plugin to override enumeration | Theoretically possible, weeks of work | `MsClrLocalAttachableHolder` is in closed-source ReSharper backend; no public extension point |
  154. | LD_PRELOAD shim faking `/tmp/dotnet-diagnostic-*` | Would only fool the listing, not the attach | Real pipes aren't there |
  155. | Custom .NET bridge program using ICorDebug | Would need to reimplement Rider's RdProtocol | Months of work, brittle across Rider versions |
  156. | Rider 2025.2 "Attach to native process via SSH" | **Windows-target only** | Per JetBrains' own announcement |
  157.  
  158. ---
  159.  
  160. ## 4. What does work today
  161.  
  162. Three approaches are confirmed working as of May 2026.
  163.  
  164. ### 4.1 dnSpy in Wine (15 minutes, easiest)
  165.  
  166. dnSpy is a full-featured managed debugger with its own UI. It runs reliably under Wine.
  167.  
  168. ```bash
  169. PFX="$HOME/.local/share/Steam/steamapps/compatdata/<appid>/pfx"
  170. mkdir -p "$PFX/drive_c/tools/dnspy"
  171. # Download dnSpyEx latest net-win64 release zip from
  172. # https://github.com/dnSpyEx/dnSpy/releases
  173. # extract into $PFX/drive_c/tools/dnspy/
  174.  
  175. ~/sbox-proton-run.sh wine "C:\\tools\\dnspy\\dnSpy.exe"
  176. # Debug → Attach to Process → sbox-dev.exe → CoreCLR → set breakpoints
  177. ```
  178.  
  179. You get breakpoints, step, locals, watch, conditional breakpoints, IL editing. UI is dated but functional. No EULA concern.
  180.  
  181. **Limitation**: Not Rider. No refactoring during debug, no IntelliSense in dnSpy's editor. Use Rider for editing, dnSpy for breakpoint inspection, Alt-Tab between them.
  182.  
  183. ### 4.2 VS Code + Microsoft `vsdbg.exe` inside Wine
  184.  
  185. This is the most "production" option. Confirmed working in the WineHQ Forums #34925 thread (Tubzur, Sept 2020) for VS/VS Code on Windows; the recipe below adapts it for VS Code on Linux driving vsdbg-in-Wine via `pipeTransport`.
  186.  
  187. **Step 1 — Get vsdbg into the prefix.** Easiest source: install VS Code's `ms-dotnettools.csharp` extension on a Windows machine, copy `%USERPROFILE%\.vscode\extensions\ms-dotnettools.csharp-<ver>-win32-x64\.debugger\` into `<prefix>/drive_c/users/steamuser/.vs-debugger/vs2022/`. Or run `aka.ms/getvsdbgps1` via `protontricks-launch ... powershell.exe` inside the prefix.
  188.  
  189. **Step 2 — Verify it runs.**
  190. ```bash
  191. ~/sbox-proton-run.sh wine 'C:\users\steamuser\.vs-debugger\vs2022\vsdbg.exe' --help
  192. ~/sbox-proton-run.sh wine 'C:\users\steamuser\.vs-debugger\vs2022\vsdbg.exe' --processList
  193. # Should list sbox-dev.exe with its Win32 PID
  194. ```
  195.  
  196. **Step 3 — Find the Win32 PID** (NOT the Linux PID):
  197. ```bash
  198. ~/sbox-proton-run.sh wine cmd /c tasklist | grep -i sbox-dev
  199. ```
  200.  
  201. **Step 4 — `.vscode/launch.json`** in the s&box source folder:
  202. ```json
  203. {
  204. "version": "0.2.0",
  205. "configurations": [
  206. {
  207. "name": "Attach sbox-dev (Wine vsdbg)",
  208. "type": "coreclr",
  209. "request": "attach",
  210. "processId": "${command:pickRemoteProcess}",
  211. "justMyCode": false,
  212. "requireExactSource": false,
  213. "pipeTransport": {
  214. "pipeCwd": "${workspaceFolder}",
  215. "pipeProgram": "/home/<you>/sbox-proton-run.sh",
  216. "pipeArgs": ["wine"],
  217. "debuggerPath": "C:\\users\\steamuser\\.vs-debugger\\vs2022\\vsdbg.exe",
  218. "quoteArgs": false
  219. },
  220. "sourceFileMap": {
  221. "Z:\\home\\<you>\\Applications\\SBox\\...\\sbox-public":
  222. "/home/<you>/Applications/SBox/.../sbox-public",
  223. "C:\\sbox":
  224. "/home/<you>/Applications/SBox/.../sbox-public"
  225. }
  226. }
  227. ]
  228. }
  229. ```
  230.  
  231. **Step 5 — F5 in VS Code, pick sbox-dev from the picker, attach.** Set breakpoints in `.cs` files, trigger in-game, hit.
  232.  
  233. **Why it works**: vsdbg accepts an explicit PID and doesn't need pipe enumeration. The `pipeTransport` reuses your Wine wrapper to launch vsdbg inside the same wineserver as sbox-dev. Attach succeeds via the standard Win32 ICorDebug local-attach path that works fine when both processes are in the same wineserver.
  234.  
  235. **Caveats**:
  236. - vsdbg EULA forbids non-Microsoft-IDE clients. Driving it from VS Code is allowed; from Rider is not.
  237. - The 2020 recipe used .NET Core 3.x. Wine has changed substantially since (esync → fsync → ntsync). The recipe should still work but no public 2024+ confirmation report exists. Test before relying on it for serious work.
  238.  
  239. ### 4.3 Native LLDB (no managed support)
  240.  
  241. For engine-level crashes in the C++ Source 2 portion of sbox, `Run → Attach to Process → sbox-dev.exe → Native (LLDB)` in native Linux Rider works. You get C++ stack traces, register state, raw memory inspection. You do not get C# information.
  242.  
  243. Useful for diagnosing engine bugs, useless for gameplay scripting.
  244.  
  245. ---
  246.  
  247. ## 5. Things to NOT do
  248.  
  249. Record of failures so the next person doesn't repeat them:
  250.  
  251. - **Don't install Win32-OpenSSH inside the Wine prefix.** Privsep architectural incompatibility, every version since 7.5 fails.
  252. - **Don't expect `DOTNET_DiagnosticPorts=tcp://...` to work for debugging on CoreCLR desktop.** It's a Mono-mobile feature.
  253. - **Don't expect bridging diagnostic pipes to enable debugging.** Diagnostic port and debugger pipe are separate systems.
  254. - **Don't try to wrap `JetBrains.Debugger.Worker` to redirect to a Wine binary.** Rider only invokes the .NET worker after classifying the process as managed; classification fails, wrapper never runs.
  255. - **Don't install Rider for Windows in the prefix expecting managed detection to work.** It uses the same Wine pipe enum API that fails for native Rider. Lots of setup, same wall.
  256. - **Don't try to make Rider drive vsdbg.** Rider speaks RdProtocol; vsdbg speaks DAP. No translator exists. Even if you wrote one, the vsdbg EULA likely forbids it.
  257. - **Don't waste time on `protontricks vcrun2022` to fix LLDB attach failures.** It only enables more native debugging, which you don't want.
  258. - **Don't open files via Rider's "Open Folder" picker inside Wine.** Use command-line argument with a `C:\` symlinked path. The Vista-style `IFileOpenDialog` crashes in Wine.
  259.  
  260. ---
  261.  
  262. ## 6. Knobs that are genuinely useful (if you push forward anyway)
  263.  
  264. For the brave still trying. These don't fix the core problem but help diagnose:
  265.  
  266. **Wine debug channels for pipe issues:**
  267. ```bash
  268. WINEDEBUG=+pipe,+server,+ntdll,+seh,+process \
  269. ~/sbox-proton-run.sh wine ... 2> /tmp/wine.log
  270. ```
  271.  
  272. **vsdbg internal logging:**
  273. ```
  274. vsdbg.exe --interpreter=vscode \
  275. --engineLogging=Z:\tmp\vsdbg-engine.log \
  276. --diagnosticLog=Z:\tmp\vsdbg-diag.log
  277. ```
  278.  
  279. **Rider remote debugger logging** (if you try Option 2 anyway):
  280. ```bash
  281. export RIDER_DEBUGGER_LOG_DIR=/tmp/rider-debug-logs
  282. export RESHARPER_LOG_CONF=/tmp/log.xml
  283. ```
  284.  
  285. **Rider JBR fixes for Wine:** Append to `rider64.exe.vmoptions`:
  286. ```
  287. -Dawt.useSystemAAFontSettings=off
  288. -Dswing.aatext=false
  289. -Dide.win.file.chooser.native=false
  290. ```
  291.  
  292. **Wine sync primitives** — fall back if you see hangs:
  293. ```bash
  294. PROTON_NO_NTSYNC=1
  295. PROTON_NO_FSYNC=1
  296. PROTON_NO_ESYNC=1
  297. ```
  298.  
  299. **Pressure-vessel access:** Steam launch options must include:
  300. ```
  301. STEAM_COMPAT_LAUNCHER_SERVICE=proton %command%
  302. ```
  303. And use `steam-runtime-launch-client --bus-name=com.steampowered.App<appid> -- wine ...` to enter the sandbox + same wineserver as sbox-dev.
  304.  
  305. **Symlink trick** to get a clean `C:\` path into the Wine view of your project:
  306. ```bash
  307. ln -sfn /path/to/sbox-public "$PFX/drive_c/sbox"
  308. # Now Wine sees C:\sbox\... instead of needing Z:\ translation
  309. ```
  310.  
  311. ---
  312.  
  313. ## 7. Why this matters and what unblocks it
  314.  
  315. The proximate cause of every JetBrains failure in this report is **Wine bug: `NtFsControlFile` doesn't implement the `FSCTL_PIPE_LIST_*` ioctls used to enumerate named pipes**. This single Wine deficiency:
  316.  
  317. - Breaks Rider's managed process detection inside Wine.
  318. - Breaks `jb-debug-ssh.exe` SSH remote attach.
  319. - Would break Visual Studio's managed-process picker if anyone ran VS under Wine.
  320.  
  321. Implementing it would unblock a substantial slice of .NET-on-Wine tooling. If you're a Wine contributor reading this: this would be a high-impact contribution.
  322.  
  323. The strategic fixes in priority order:
  324.  
  325. 1. **Facepunch ships a native Linux build of sbox** (issue sbox-issues#7428). The whole problem evaporates because both sbox and Rider would speak the same Linux IPC. This requires Facepunch effort and Source 2 .so files they currently don't ship.
  326. 2. **Wine implements pipe enumeration**. Single-bug fix, broad benefit.
  327. 3. **JetBrains adds an "explicit-PID, force-debugger-type" attach mode.** Would let Rider skip the broken enumeration step entirely. Has been requested in YouTrack; no movement.
  328. 4. **Microsoft loosens the vsdbg EULA** to allow Rider as a client. Has been requested (dotnet/core#4788) and rejected.
  329.  
  330. None of these is happening on a timeline you can plan around. Use dnSpy or VS Code today.
  331.  
  332. ---
  333.  
  334. ## 8. References
  335.  
  336. Confirmed working / authoritative:
  337. - WineHQ Forum thread #34925 — vsdbg under Wine (Sept 2020): `https://forum.winehq.org/viewtopic.php?t=34925`
  338. - Microsoft MIEngine issue #1105 — vsdbg-in-Wine cross-post
  339. - Microsoft Learn — diagnostic port docs: `learn.microsoft.com/en-us/dotnet/core/diagnostics/diagnostic-port`
  340. - dotnet/runtime issue #88177 — DOTNET_DiagnosticPorts listen mode broken on CoreCLR desktop
  341. - dotnet/core issue #4788 — vsdbg licensing discussion
  342. - dotnet/core issue #505 — historical clrdbg removal from Rider
  343. - dotnet/runtime issue #65017 — dbgshim moved to dotnet/diagnostics
  344. - JetBrains Rider docs — SSH Remote Debugging: `jetbrains.com/help/rider/SSH_Remote_Debugging.html`
  345. - Steam Linux Runtime — pressure-vessel docs at `gitlab.steamos.cloud/steamrt`
  346. - Maxim Arshinov's "Debugging Docker Compose Solutions in JetBrains Rider: A Deep Dive" on dev.to — reverse-engineered Rider's remote debug pipeline
  347.  
  348. s&box-specific:
  349. - Steam Community Guide ID 3697987209 — running sbox editor under Proton
  350. - sbox-issues #7428 — Native Linux build feature request
  351. - sbox-issues #663 — Native Linux Build discussion (Facepunch declined)
  352. - sbox-public #4147, #4891, #5959, #5205 — Rider attach issues (Windows-side)
  353. - sbox-public #485 — Saladin1812's Linux port attempt (blocked on missing Source 2 .so)
  354.  
  355. Tooling:
  356. - dnSpyEx releases: `github.com/dnSpyEx/dnSpy/releases`
  357. - VS Code C# extension: `marketplace.visualstudio.com/items?itemName=ms-dotnettools.csharp`
  358. - vsdbg installer: `aka.ms/getvsdbgps1` (PowerShell), `aka.ms/getvsdbgsh` (bash)
  359.  
  360. ---
  361.  
  362. ## 9. Minimum-viable working config (copy-paste)
  363.  
  364. If you ignore everything else in this report, do this:
  365.  
  366. ```bash
  367. # 1. Make wrapper script that enters the sandbox + same wineserver as sbox-dev.
  368. # Set Steam launch options to STEAM_COMPAT_LAUNCHER_SERVICE=proton %command% first.
  369. cat > ~/sbox-proton-run.sh <<'EOF'
  370. #!/usr/bin/env bash
  371. APPID=2231310667 # adjust if your sbox compat ID differs
  372. SLR_LAUNCH_CLIENT="$HOME/.local/share/Steam/steamapps/common/SteamLinuxRuntime_4/pressure-vessel/bin/steam-runtime-launch-client"
  373. exec "$SLR_LAUNCH_CLIENT" --bus-name=com.steampowered.App${APPID} -- "$@"
  374. EOF
  375. chmod +x ~/sbox-proton-run.sh
  376.  
  377. # 2. Get dnSpy.
  378. PFX="$HOME/.local/share/Steam/steamapps/compatdata/2231310667/pfx"
  379. mkdir -p "$PFX/drive_c/tools/dnspy"
  380. # Download latest dnSpy-net-win64.zip from github.com/dnSpyEx/dnSpy/releases,
  381. # extract into "$PFX/drive_c/tools/dnspy/".
  382.  
  383. # 3. Launch sbox via Steam, wait for it to be running, then:
  384. ~/sbox-proton-run.sh wine "C:\\tools\\dnspy\\dnSpy.exe"
  385. # Debug → Attach to Process → sbox-dev.exe → CoreCLR.
  386. # Set breakpoints, trigger code in-game, hit.
  387. ```
  388.  
  389. That's it. ~15 minutes from zero to breakpoints. No Rider, no vsdbg, no SSH, no .NET SDK install.
  390.  
  391. ---
  392.  
  393. ## 10. Acknowledgements and final thoughts
  394.  
  395. This report represents several days of debugging by one person attempting every reasonable angle. The conclusion that native-Linux-Rider managed-debugging of Wine-CoreCLR is structurally impossible should be treated as **strong but rebuttable** — if you find a working recipe that doesn't appear here, please publish it.
  396.  
  397. The s&box community on Linux is small but determined. The lack of a documented working Rider recipe (as of May 2026, after extensive search across sbox-public, sbox-issues, Facepunch forums, Reddit, Steam guides, JetBrains community, and Discord archives) suggests either nobody has solved it or nobody has bothered to write it down. Both are equally bad outcomes.
  398.  
  399. If you came here looking for hope: there isn't much in the short term. Use dnSpy, file your YouTrack tickets, upvote sbox-issues#7428, and write Wine patches if you can. The path forward exists; it just doesn't go through the IDE you wanted.
  400.  
  401. Good luck.
  402.  
  403. ---
  404.  
  405. *This document is released into the public domain. Copy, fork, repost, correct, extend.*
Add Comment
Please, Sign In to add comment