feat(v2): add runtime.ResetSignalHandlers() for Linux panic recovery#4921
Conversation
📝 WalkthroughWalkthroughAdds a Linux-specific runtime helper, Changes
Sequence Diagram(s)sequenceDiagram
participant App as Go app (caller)
participant Runtime as runtime.ResetSignalHandlers()
participant C as cgo C helper
participant OS as Kernel / libc / WebKit handlers
App->>Runtime: call ResetSignalHandlers()
Runtime->>C: call fix_all_signals()
C->>OS: set sigaction with SA_ONSTACK for SIGSEGV,SIGBUS,SIGFPE,SIGABRT
OS-->>C: ack
C-->>Runtime: return
Runtime-->>App: return
Note right of OS: Signals now delivered with SA_ONSTACK
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Possibly related PRs
Suggested labels
Suggested reviewers
Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing touches
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Add a new runtime function that allows users to reset signal handlers
before code that might panic from nil pointer dereferences.
On Linux, WebKit installs signal handlers without the SA_ONSTACK flag,
which prevents Go from properly recovering from panics caused by
SIGSEGV and other signals. This function adds SA_ONSTACK to the
relevant signal handlers (SIGSEGV, SIGBUS, SIGFPE, SIGABRT).
Usage:
```go
go func() {
defer func() {
if err := recover(); err != nil {
log.Printf("Recovered: %v", err)
}
}()
runtime.ResetSignalHandlers()
// Code that might panic...
}()
```
The function is a no-op on macOS and Windows.
Fixes #3965
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
efef6b1 to
6395679
Compare
Deploying wails with
|
| Latest commit: |
982ddd2
|
| Status: | ✅ Deploy successful! |
| Preview URL: | https://16c34357.wails.pages.dev |
| Branch Preview URL: | https://fix-linux-panic-recovery-run.wails.pages.dev |
Add an example that demonstrates the Linux signal handler issue (#3965) and verifies the fix using runtime.ResetSignalHandlers(). The example includes: - A Greet function that triggers a nil pointer dereference after a delay - Auto-call from frontend after 5 seconds - README with reproduction steps Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
|
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Fix all issues with AI agents
In `@v2/examples/panic-recovery-test/frontend/src/main.js`:
- Around line 7-15: The HTML template has an extra closing </div> with no
matching opener; fix by adding a corresponding opening wrapper div (e.g., <div
class="container">) before the <div class="result" id="result"> so the DOM nests
correctly around the `#logo`, `#result` and `#input` elements, then verify the greet()
button and element IDs (name, result, input, logo) still match expected
selectors and event handlers.
🧹 Nitpick comments (7)
v2/examples/panic-recovery-test/README.md (3)
9-12: Add language identifier to fenced code block.The error output code block should specify a language for proper syntax highlighting.
📝 Suggested fix
-``` +```text signal 11 received but handler not on signal stack fatal error: non-Go code set up signal handler without SA_ONSTACK flag -``` +```
58-60: Add language identifier to fenced code block.The expected output code block should specify a language for consistency.
📝 Suggested fix
-``` +```text ------------------------------"invalid memory address or nil pointer dereference" -``` +```
73-76: Convert bare URLs to proper markdown links.Using markdown link syntax improves readability and follows markdown best practices.
📝 Suggested fix
## Related -- Issue: https://github.com/wailsapp/wails/issues/3965 -- Original fix PR: https://github.com/wailsapp/wails/pull/2152 +- Issue: [`#3965`](https://github.com/wailsapp/wails/issues/3965) +- Original fix PR: [`#2152`](https://github.com/wailsapp/wails/pull/2152)v2/examples/panic-recovery-test/frontend/src/main.js (1)
31-42: Redundant try-catch block.The outer
try-catchonly catches synchronous errors, butGreet()returns a Promise. The.catch()handler already handles Promise rejections, making the outer try-catch unnecessary.♻️ Suggested simplification
// Call App.Greet(name) - try { - Greet(name) - .then((result) => { - // Update result with data back from App.Greet() - resultElement.innerText = result; - }) - .catch((err) => { - console.error(err); - }); - } catch (err) { - console.error(err); - } + Greet(name) + .then((result) => { + // Update result with data back from App.Greet() + resultElement.innerText = result; + }) + .catch((err) => { + console.error(err); + });v2/examples/panic-recovery-test/frontend/wailsjs/runtime/runtime.d.ts (2)
21-26: Minor formatting inconsistency in interface declaration.The
Screeninterface has inconsistent spacing around colons compared to other interfaces (width : numbervswidth: number).📝 Suggested fix
export interface Screen { isCurrent: boolean; isPrimary: boolean; - width : number - height : number + width: number; + height: number; }
239-249: Minor formatting inconsistencies in function declarations.A few function declarations have minor formatting issues: missing space after comma, and missing semicolons.
📝 Suggested fixes
// [OnFileDrop](https://wails.io/docs/reference/runtime/draganddrop#onfiledrop) // OnFileDrop listens to drag and drop events and calls the callback with the coordinates of the drop and an array of path strings. -export function OnFileDrop(callback: (x: number, y: number ,paths: string[]) => void, useDropTarget: boolean) :void +export function OnFileDrop(callback: (x: number, y: number, paths: string[]) => void, useDropTarget: boolean): void; // [OnFileDropOff](https://wails.io/docs/reference/runtime/draganddrop#dragandddropoff) // OnFileDropOff removes the drag and drop listeners and handlers. -export function OnFileDropOff() :void +export function OnFileDropOff(): void; // Check if the file path resolver is available export function CanResolveFilePaths(): boolean; // Resolves file paths for an array of files -export function ResolveFilePaths(files: File[]): void +export function ResolveFilePaths(files: File[]): void;v2/examples/panic-recovery-test/frontend/wailsjs/runtime/runtime.js (1)
59-62: Consider using modern spread syntax for clarity.The expression
[eventName].slice.call(arguments)works but is non-idiomatic. Using rest parameters or spread syntax would be clearer and more maintainable.♻️ Suggested improvement
-export function EventsEmit(eventName) { - let args = [eventName].slice.call(arguments); - return window.runtime.EventsEmit.apply(null, args); +export function EventsEmit(eventName, ...args) { + return window.runtime.EventsEmit(eventName, ...args); }
| document.querySelector('#app').innerHTML = ` | ||
| <img id="logo" class="logo"> | ||
| <div class="result" id="result">Please enter your name below 👇</div> | ||
| <div class="input-box" id="input"> | ||
| <input class="input" id="name" type="text" autocomplete="off" /> | ||
| <button class="btn" onclick="greet()">Greet</button> | ||
| </div> | ||
| </div> | ||
| `; |
There was a problem hiding this comment.
Fix unmatched HTML closing tag.
The template has an unmatched closing </div> tag on line 14. The structure shows opening tags for result and input-box divs, but there's an extra closing tag without a corresponding opening container.
🐛 Suggested fix - add opening container div
document.querySelector('#app').innerHTML = `
- <img id="logo" class="logo">
+ <div>
+ <img id="logo" class="logo">
<div class="result" id="result">Please enter your name below 👇</div>
<div class="input-box" id="input">
<input class="input" id="name" type="text" autocomplete="off" />
<button class="btn" onclick="greet()">Greet</button>
</div>
</div>
`;📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| document.querySelector('#app').innerHTML = ` | |
| <img id="logo" class="logo"> | |
| <div class="result" id="result">Please enter your name below 👇</div> | |
| <div class="input-box" id="input"> | |
| <input class="input" id="name" type="text" autocomplete="off" /> | |
| <button class="btn" onclick="greet()">Greet</button> | |
| </div> | |
| </div> | |
| `; | |
| document.querySelector('#app').innerHTML = ` | |
| <div> | |
| <img id="logo" class="logo"> | |
| <div class="result" id="result">Please enter your name below 👇</div> | |
| <div class="input-box" id="input"> | |
| <input class="input" id="name" type="text" autocomplete="off" /> | |
| <button class="btn" onclick="greet()">Greet</button> | |
| </div> | |
| </div> | |
| `; |
🤖 Prompt for AI Agents
In `@v2/examples/panic-recovery-test/frontend/src/main.js` around lines 7 - 15,
The HTML template has an extra closing </div> with no matching opener; fix by
adding a corresponding opening wrapper div (e.g., <div class="container">)
before the <div class="result" id="result"> so the DOM nests correctly around
the `#logo`, `#result` and `#input` elements, then verify the greet() button and
element IDs (name, result, input, logo) still match expected selectors and event
handlers.
| "node": "^10 || ^12 || >=14" | ||
| } | ||
| }, | ||
| "node_modules/rollup": { |
There was a problem hiding this comment.
High severity vulnerability may affect your project—review required:
Line 569 lists a dependency (rollup) with a known High severity vulnerability.
ℹ️ Why this matters
Affected versions of rollup are vulnerable to Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting').
To resolve this comment:
Check if you use Rollup to bundle JavaScript with import.meta.url and the output format is set to cjs, umd, or iife formats, while allowing users to inject scriptless HTML elements with unsanitized name attributes.
- If you're affected, upgrade this dependency to at least version 3.29.5 at v3/examples/dev/frontend/package-lock.json.
- If you're not affected, comment
/fp we don't use this [condition]
💬 Ignore this finding
To ignore this, reply with:
/fp <comment>for false positive/ar <comment>for acceptable risk/other <comment>for all other reasons
You can view more details on this finding in the Semgrep AppSec Platform here.


Summary
runtime.ResetSignalHandlers()function to allow panic recovery from nil pointer dereferences on LinuxProblem
On Linux, WebKit (used for the webview) installs signal handlers without the
SA_ONSTACKflag. This prevents Go from properly recovering from panics caused by SIGSEGV (nil pointer dereference) and other memory access violations. Users experience crashes with:Even with
defer/recover(), the panic cannot be caught.Solution
Add a new runtime function that resets signal handlers with the proper
SA_ONSTACKflag:The function must be called immediately before potentially panicking code because WebKit may reset the handlers at any time.
Changes
v2/pkg/runtime/signal_linux.go- Linux implementation using cgov2/pkg/runtime/signal_other.go- No-op stub for macOS/Windowsv2/examples/panic-recovery-test/- Example project to reproduce/verifywebsite/docs/reference/runtime/intro.mdx- API documentationwebsite/docs/guides/linux.mdx- Troubleshooting guideTest plan
How to reproduce and verify
Build the example:
cd v2/examples/panic-recovery-test wails build -tags webkit2_41Run the application:
Wait ~10 seconds (the app auto-calls
Greetafter 5s, then waits another 5s before the nil pointer dereference)Expected result (with fix)
The panic is recovered and you see:
The application continues running.
To verify the fix is needed
Comment out the
runtime.ResetSignalHandlers()call inapp.goand rebuild. The application will crash with a fatal signal 11 error.Fixes #3965
🤖 Generated with Claude Code
Summary by CodeRabbit
New Features
Documentation
Examples
✏️ Tip: You can customize this high-level summary in your review settings.