Skip to content

Call vips_shutdown on exit to prevent segfault#1412

Closed
felixbuenemann wants to merge 1 commit intolibvips:masterfrom
felixbuenemann:fix-missing-shutdown
Closed

Call vips_shutdown on exit to prevent segfault#1412
felixbuenemann wants to merge 1 commit intolibvips:masterfrom
felixbuenemann:fix-missing-shutdown

Conversation

@felixbuenemann
Copy link
Copy Markdown
Contributor

Register vips_shutdown as an atexit handler to drain the libvips thread pool before Python tears down. Without this, worker threads waiting on a condition variable can try to execute code from unmapped memory during Python's final GC pass, causing an intermittent segfault on exit.

The function pointer is cached before registering (same pattern as _remove_log_handler) since ffi lookups can fail during shutdown. Calling vips_shutdown multiple times is safe per the libvips docs, so it doesn't matter if pyvips.shutdown() was already called manually.

Register vips_shutdown as an atexit handler to drain the libvips
thread pool before Python tears down. Without this, worker threads
waiting on a condition variable can try to execute code from unmapped
memory during Python's final GC pass, causing an intermittent segfault
on exit.

The function pointer is cached before registering (same pattern as
_remove_log_handler) since ffi lookups can fail during shutdown.
Calling vips_shutdown multiple times is safe per the libvips docs,
so it doesn't matter if pyvips.shutdown() was already called manually.
@kleisauke
Copy link
Copy Markdown
Member

Do you have a reproducer for this? This change effectively reverts commit libvips/libvips@af61d37 (but for Python only).

Note to self: check if commit kleisauke/libvips@f75675f could be an alternative to this.

@felixbuenemann
Copy link
Copy Markdown
Contributor Author

felixbuenemann commented Mar 30, 2026

@kleisauke This happened to me when working on new libvips code the was using vips_sink_disc under the hood (which spins up worker threads) and testing that code from pyvips. The crash would happen when python exited. I don't have a standalone reproducer, since that code isn't in master, but I can try to create one.

@kleisauke
Copy link
Copy Markdown
Member

A reproducer would be very helpful. Just to confirm, are you referring to this CI run?https://github.com/libvips/libvips/actions/runs/23707203380/job/69061006825

If so, that was fixed in commit libvips/libvips@efaa772, although the 8.18 branch still needs to be merged back into master.

@felixbuenemann
Copy link
Copy Markdown
Contributor Author

@kleisauke No, it was unrelated. I can't reproduce the problem anymore. OK if I close this PR?

@kleisauke
Copy link
Copy Markdown
Member

Feel free to close. IIRC, I've encountered this once with new code as well, but that was due to a missing call to vips__region_no_ownership().

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.

2 participants