fix: prevent SIGABRT crash on permission-request signal
Bump puregotk-webkit to v0.0.14 which registers the missing
DeviceInfoPermissionRequest GType function pointer. Without this, any
page calling navigator.mediaDevices.enumerateDevices() triggered a nil
function panic converted to SIGABRT by debug.SetTraceback("crash").
Also add safeGLibType() defensive wrapper around GType lookups in
detectPermissionRequestKind so future unregistered types degrade
gracefully instead of crashing.- commit
- 98033054f5e5e58e9fd498adc1902827ae93a42e
- author
- brice · · 2026-03-06 05:55 UTC
- parent
- 3458ddd
- signature
- GPG Verified
CD88F9E564E0102646FB6077A1A07C7C7C3E349D· arch-gpg Verified for the committer email
3 files · +24 -5
M go.mod +1 -1
| @@ -3,7 +3,7 @@ module github.com/bnema/dumber | |||
| 3 | 3 | go 1.26 | |
| 4 | 4 | ||
| 5 | 5 | require ( | |
| 6 | - | github.com/bnema/puregotk-webkit v0.0.13 | |
| 6 | + | github.com/bnema/puregotk-webkit v0.0.14 | |
| 7 | 7 | github.com/charmbracelet/bubbles v1.0.0 | |
| 8 | 8 | github.com/charmbracelet/bubbletea v1.3.10 | |
| 9 | 9 | github.com/charmbracelet/lipgloss v1.1.0 | |
| @@ -3,7 +3,7 @@ module github.com/bnema/dumber | |||||
| 3 | go 1.26 | 3 | go 1.26 | ||
| 4 | 4 | ||||
| 5 | require ( | 5 | require ( | ||
| 6 | - | github.com/bnema/puregotk-webkit v0.0.13 | 6 | + | github.com/bnema/puregotk-webkit v0.0.14 |
| 7 | github.com/charmbracelet/bubbles v1.0.0 | 7 | github.com/charmbracelet/bubbles v1.0.0 | ||
| 8 | github.com/charmbracelet/bubbletea v1.3.10 | 8 | github.com/charmbracelet/bubbletea v1.3.10 | ||
| 9 | github.com/charmbracelet/lipgloss v1.1.0 | 9 | github.com/charmbracelet/lipgloss v1.1.0 | ||
M go.sum +2 -0 generated file: collapsed
M internal/infrastructure/webkit/webview.go +21 -4
| @@ -1092,15 +1092,32 @@ const ( | |||
| 1092 | 1092 | ) | |
| 1093 | 1093 | ||
| 1094 | 1094 | func detectPermissionRequestKind(ctx context.Context, requestPtr uintptr) permissionRequestKind { | |
| 1095 | - | if isPermissionRequestType(ctx, requestPtr, webkit.UserMediaPermissionRequestGLibType()) { | |
| 1096 | - | return permissionRequestKindUserMedia | |
| 1095 | + | if gtype, ok := safeGLibType(webkit.UserMediaPermissionRequestGLibType); ok { | |
| 1096 | + | if isPermissionRequestType(ctx, requestPtr, gtype) { | |
| 1097 | + | return permissionRequestKindUserMedia | |
| 1098 | + | } | |
| 1097 | 1099 | } | |
| 1098 | - | if isPermissionRequestType(ctx, requestPtr, webkit.DeviceInfoPermissionRequestGLibType()) { | |
| 1099 | - | return permissionRequestKindDeviceInfo | |
| 1100 | + | if gtype, ok := safeGLibType(webkit.DeviceInfoPermissionRequestGLibType); ok { | |
| 1101 | + | if isPermissionRequestType(ctx, requestPtr, gtype) { | |
| 1102 | + | return permissionRequestKindDeviceInfo | |
| 1103 | + | } | |
| 1100 | 1104 | } | |
| 1101 | 1105 | return permissionRequestKindUnknown | |
| 1102 | 1106 | } | |
| 1103 | 1107 | ||
| 1108 | + | // safeGLibType calls a GType accessor function, recovering from panics caused | |
| 1109 | + | // by unregistered (nil) puregotk function pointers. Returns the GType and true | |
| 1110 | + | // on success, or zero and false if the call panicked. | |
| 1111 | + | func safeGLibType(fn func() gtypes.GType) (gtype gtypes.GType, ok bool) { | |
| 1112 | + | defer func() { | |
| 1113 | + | if r := recover(); r != nil { | |
| 1114 | + | gtype = 0 | |
| 1115 | + | ok = false | |
| 1116 | + | } | |
| 1117 | + | }() | |
| 1118 | + | return fn(), true | |
| 1119 | + | } | |
| 1120 | + | ||
| 1104 | 1121 | func isPermissionRequestType(ctx context.Context, requestPtr uintptr, requestType gtypes.GType) bool { | |
| 1105 | 1122 | return gobjectTypeCheckInstanceIsAByPtr(ctx, requestPtr, requestType) | |
| 1106 | 1123 | } | |
| @@ -1092,15 +1092,32 @@ const ( | |||||
| 1092 | ) | 1092 | ) | ||
| 1093 | 1093 | ||||
| 1094 | func detectPermissionRequestKind(ctx context.Context, requestPtr uintptr) permissionRequestKind { | 1094 | func detectPermissionRequestKind(ctx context.Context, requestPtr uintptr) permissionRequestKind { | ||
| 1095 | - | if isPermissionRequestType(ctx, requestPtr, webkit.UserMediaPermissionRequestGLibType()) { | 1095 | + | if gtype, ok := safeGLibType(webkit.UserMediaPermissionRequestGLibType); ok { |
| 1096 | - | return permissionRequestKindUserMedia | 1096 | + | if isPermissionRequestType(ctx, requestPtr, gtype) { |
| 1097 | + | return permissionRequestKindUserMedia | |||
| 1098 | + | } | |||
| 1097 | } | 1099 | } | ||
| 1098 | - | if isPermissionRequestType(ctx, requestPtr, webkit.DeviceInfoPermissionRequestGLibType()) { | 1100 | + | if gtype, ok := safeGLibType(webkit.DeviceInfoPermissionRequestGLibType); ok { |
| 1099 | - | return permissionRequestKindDeviceInfo | 1101 | + | if isPermissionRequestType(ctx, requestPtr, gtype) { |
| 1102 | + | return permissionRequestKindDeviceInfo | |||
| 1103 | + | } | |||
| 1100 | } | 1104 | } | ||
| 1101 | return permissionRequestKindUnknown | 1105 | return permissionRequestKindUnknown | ||
| 1102 | } | 1106 | } | ||
| 1103 | 1107 | ||||
| 1108 | + | // safeGLibType calls a GType accessor function, recovering from panics caused | |||
| 1109 | + | // by unregistered (nil) puregotk function pointers. Returns the GType and true | |||
| 1110 | + | // on success, or zero and false if the call panicked. | |||
| 1111 | + | func safeGLibType(fn func() gtypes.GType) (gtype gtypes.GType, ok bool) { | |||
| 1112 | + | defer func() { | |||
| 1113 | + | if r := recover(); r != nil { | |||
| 1114 | + | gtype = 0 | |||
| 1115 | + | ok = false | |||
| 1116 | + | } | |||
| 1117 | + | }() | |||
| 1118 | + | return fn(), true | |||
| 1119 | + | } | |||
| 1120 | + | ||||
| 1104 | func isPermissionRequestType(ctx context.Context, requestPtr uintptr, requestType gtypes.GType) bool { | 1121 | func isPermissionRequestType(ctx context.Context, requestPtr uintptr, requestType gtypes.GType) bool { | ||
| 1105 | return gobjectTypeCheckInstanceIsAByPtr(ctx, requestPtr, requestType) | 1122 | return gobjectTypeCheckInstanceIsAByPtr(ctx, requestPtr, requestType) | ||
| 1106 | } | 1123 | } | ||