fix(v3/linux): use g_bytes_new instead of g_bytes_new_static for Go slices#4923
Conversation
The Focus() method was missing a nil/destroyed check on w.impl, causing a SIGSEGV when Focus() is called on a window that has been hidden and potentially destroyed (e.g., when clicking the dock icon after hiding the window on macOS). This aligns Focus() with Show() and Hide() which already have proper guards against nil/destroyed window implementations. Fixes wailsapp#4890 Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
…lices g_bytes_new_static expects truly static data that is never freed or moved, but Go's garbage collector can move or free slice memory at any time. This causes SIGSEGV crashes in the GTK event loop when the GC runs and frees memory that GTK still references. The fix replaces g_bytes_new_static with g_bytes_new, which copies the data to C-owned memory that is safe from Go's GC. Also fixes memory leak in setIcon() by adding proper g_bytes_unref and g_object_unref calls for the GBytes and stream objects. Changes: - linux_cgo.go: Replace g_bytes_new_static with g_bytes_new (4 places) - linux_cgo.go: Add cleanup in setIcon() for gbytes and stream - linux_purego.go: Add gBytesNew binding and use it instead of static Fixes wailsapp#4864 Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
WalkthroughReplaced static GBytes usage with dynamic GBytes allocations and added explicit unref/defer calls to ensure C memory isn't tied to Go GC; added guards to avoid creating bytes for empty images; registered a new gBytesNew pointer in pure-Go path; added a nil/destroyed check in WebviewWindow.Focus; updated changelog. Changes
Sequence Diagram(s)(Skipped — changes are internal memory-management and small control checks that do not introduce a new multi-component sequential flow.) Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Suggested labels
Poem
🚥 Pre-merge checks | ✅ 3 | ❌ 2❌ Failed checks (1 warning, 1 inconclusive)
✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing touches
🧪 Generate unit tests (beta)
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 |
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Fix all issues with AI agents
In `@v3/pkg/application/linux_cgo.go`:
- Around line 665-669: The code takes &slice[0] on icon/bitmap byte slices
(e.g., in linuxApp.setIcon) which will panic for zero-length slices; add a guard
that checks len(icon)==0 (or len(bitmap)==0) and return early (no-op) or handle
as an empty icon before taking &icon[0]; apply the same pattern to the other
similar functions referenced (the blocks at the other occurrences) so you never
call C.g_bytes_new with &slice[0] when the slice is empty.
In `@v3/pkg/application/linux_purego.go`:
- Around line 1196-1200: The code calls
gBytesNew(uintptr(unsafe.Pointer(&img.Pix[0])), len(img.Pix)) without checking
for an empty img.Pix, which can panic; before taking &img.Pix[0] in the
pngToImage success branch, add a guard like if len(img.Pix) == 0 { /* handle
empty icon: skip gBytesNew / set gbytes=nil / use empty buffer */ } else {
gbytes := gBytesNew(uintptr(unsafe.Pointer(&img.Pix[0])), len(img.Pix)) ... } so
pngToImage, img.Pix, and gBytesNew are only used when img.Pix has length > 0.
Adds guards to check for empty slices before taking &slice[0] which would panic on empty input. Affects setIcon(), menuItemAddProperties(), menuItemSetBitmap(), and runQuestionDialog() in both CGO and purego. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
There was a problem hiding this comment.
Actionable comments posted: 0
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
v3/pkg/application/linux_cgo.go (1)
841-858:⚠️ Potential issue | 🟡 MinorUnref the temporary
GdkPixbufafter creating theGtkImage.
gtk_image_new_from_pixbuf()adds its own reference and does not take ownership, so the localpixBufmust be unref'd to avoid memory leaks. Apply in these three locations.♻️ Proposed fix (apply to each site)
pixBuf := C.gdk_pixbuf_new_from_bytes( gbytes, C.GDK_COLORSPACE_RGB, 1, // has_alpha 8, C.int(img.Bounds().Dx()), C.int(img.Bounds().Dy()), C.int(img.Stride), ) image := C.gtk_image_new_from_pixbuf(pixBuf) +C.g_object_unref(C.gpointer(pixBuf)) C.gtk_widget_set_visible((*C.GtkWidget)(image), C.gboolean(1))Also applies to: 923-940, 2205-2223
|
…lices (wailsapp#4923) * fix(v3): add nil check to Focus() to prevent SIGSEGV after Hide The Focus() method was missing a nil/destroyed check on w.impl, causing a SIGSEGV when Focus() is called on a window that has been hidden and potentially destroyed (e.g., when clicking the dock icon after hiding the window on macOS). This aligns Focus() with Show() and Hide() which already have proper guards against nil/destroyed window implementations. Fixes wailsapp#4890 Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix(v3/linux): use g_bytes_new instead of g_bytes_new_static for Go slices g_bytes_new_static expects truly static data that is never freed or moved, but Go's garbage collector can move or free slice memory at any time. This causes SIGSEGV crashes in the GTK event loop when the GC runs and frees memory that GTK still references. The fix replaces g_bytes_new_static with g_bytes_new, which copies the data to C-owned memory that is safe from Go's GC. Also fixes memory leak in setIcon() by adding proper g_bytes_unref and g_object_unref calls for the GBytes and stream objects. Changes: - linux_cgo.go: Replace g_bytes_new_static with g_bytes_new (4 places) - linux_cgo.go: Add cleanup in setIcon() for gbytes and stream - linux_purego.go: Add gBytesNew binding and use it instead of static Fixes wailsapp#4864 Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix(linux): add empty slice guards to prevent panic Adds guards to check for empty slices before taking &slice[0] which would panic on empty input. Affects setIcon(), menuItemAddProperties(), menuItemSetBitmap(), and runQuestionDialog() in both CGO and purego. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> --------- Co-authored-by: ddmoney420 <ddmoney420@users.noreply.github.com> Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com> Co-authored-by: Lea Anthony <lea.anthony@gmail.com>


Summary
g_bytes_new_staticwithg_bytes_newfor all Go slice datasetIcon()by adding proper cleanupgBytesNewbinding to purego implementationProblem
g_bytes_new_staticis documented as expecting "static" data that is never freed or moved. However, the Linux code was passing Go slice data (&icon[0],&img.Pix[0]) which can be moved or freed by Go's garbage collector at any time.When Go's GC runs, the memory passed to GTK becomes invalid, causing a SIGSEGV crash in
g_application_run(the GTK event loop).From the GLib docs:
Solution
Use
g_bytes_newinstead, which copies the data to C-owned memory that is safe from Go's GC.Changes
linux_cgo.gog_bytes_new_static→g_bytes_new(4 places)linux_cgo.godefer C.g_bytes_unref(gbytes)anddefer C.g_object_unref(stream)insetIcon()linux_purego.gogBytesNewfunction bindinglinux_purego.gogBytesNewStatic→gBytesNewTest plan
Note: The correlation with "array parameters" in the original issue is likely because array-heavy operations increase memory pressure, triggering GC more frequently and exposing this race condition faster.
Fixes #4864
🤖 Generated with Claude Code
Summary by CodeRabbit
Bug Fixes
Improvements