Skip to content

Fix segfault in GC finalisers - #18

Open
talex5 wants to merge 1 commit into
Octachron:mainfrom
talex5:fix-gc
Open

Fix segfault in GC finalisers#18
talex5 wants to merge 1 commit into
Octachron:mainfrom
talex5:fix-gc

Conversation

@talex5

@talex5 talex5 commented Aug 1, 2025

Copy link
Copy Markdown
Contributor

When a C struct refers to other C memory, we need to keep the targets alive. This is done by attaching a finaliser to the OCaml value pointing at the first struct, where the finaliser holds an OCaml value that points at the targets.

Previously, this was done using [| Obj.repr field1; Obj.repr field2 |]. However, this fails if field1 is a float and field2 isn't as OCaml will try to convert it to a float-array. This will cause a segfault.

It now uses a tuple instead when there are multiple fields, and adds the missing Sys.opaque_identity (as suggested by Florian Angeletti).

The old code was also catching and ignoring Invalid_argument (6b636fb). I removed this as I don't think it can happen, and if it does we probably want to know about it. Added a comment about when this happens.

Fixes #17.

@talex5
talex5 force-pushed the fix-gc branch 3 times, most recently from 2dc43c6 to 6f025cf Compare August 8, 2025 15:26
Comment thread aster/structured.ml Outdated
]
match exprs with
| [] -> body
| [x] -> [%expr Vk__helpers.keep_alive [%e Exp.array [x]] [%e owner]; [%e body]]

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Even a size-one array can be pick up the flotarray optimized layout. I would suggest to use a ref or a ( (), x) tuple.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does it matter if it does? The optimised layout only causes a problem if it treats non-floats as floats.

Probably there should be a function to say whether a type needs to be kept alive and we could use that to skip floats completely.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually, there's no reason to wrap a single value in anything. I've updated the PR.

@talex5
talex5 force-pushed the fix-gc branch 4 times, most recently from 4c027ee to 154b334 Compare August 17, 2025 09:55
When a C struct refers to other C memory, we need to keep the targets
alive. This is done by attaching a finaliser to the OCaml value pointing
at the first struct, where the finaliser holds an OCaml value that
points at the targets.

Previously, this was done using [| Obj.repr field1; Obj.repr field2 |].
However, this fails if `field1` is a float and `field2` isn't as OCaml
will try to convert it to a float-array. This will cause a segfault.

It now uses a tuple instead when there are multiple fields, and adds the
missing `Sys.opaque_identity` (as suggested by Florian Angeletti).

Fixes Octachron#17.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Using Obj.repr in arrays leads to segfaults

2 participants