Thanks to visit codestin.com
Credit goes to github.com

Skip to content

CIFuzz: integrate ThreadSanitizer#4981

Draft
kleisauke wants to merge 27 commits intolibvips:masterfrom
kleisauke:cifuzz-add-tsan
Draft

CIFuzz: integrate ThreadSanitizer#4981
kleisauke wants to merge 27 commits intolibvips:masterfrom
kleisauke:cifuzz-add-tsan

Conversation

@kleisauke
Copy link
Copy Markdown
Member

@kleisauke kleisauke commented Mar 28, 2026

Opened as a draft since ThreadSanitizer is not officially supported by CIFuzz.

Context: #4713 (comment).
Depends on: google/oss-fuzz#15235.

@kleisauke kleisauke force-pushed the cifuzz-add-tsan branch 2 times, most recently from 8a948f2 to 58c1cfc Compare March 29, 2026 13:40
Use `libraries` instead of `requires` when calling `pkg.generate()`
to make the configuration succeed with internal dependencies (i.e.
subprojects).

Non-functional change.
@kleisauke
Copy link
Copy Markdown
Member Author

This is starting to take shape. I've opened PR #4985 and google/oss-fuzz#15235, which this PR depends on.

TSan is also far more reliable when GLib is built with it, which allows me to remove most of the previously needed suppressions. :)

@kleisauke kleisauke force-pushed the cifuzz-add-tsan branch 2 times, most recently from 3313b54 to 6aa50c5 Compare March 30, 2026 17:03
@kleisauke
Copy link
Copy Markdown
Member Author

The changeset at kleisauke/libvips@8ed96ff...6967b16 (which I'll split out later) fixes all known data races found in this PR. The TSan suppressions now apply only to GLib:

## The suppressions below match only the top frame of report stacks
# GClosure mixes atomic compare and exchange with non atomic reads
# (read of cl->n_guards and cl->derivative_flag is non atomic)
# https://gitlab.gnome.org/GNOME/glib/-/issues/1672
race_top:closure_invoke_notifiers
race_top:g_cclosure_marshal_VOID__POINTER
race_top:vips_INT__VOID
## The suppressions below match all frames of report stacks
# Unsynchronized read of once->status from g_once
# https://gitlab.gnome.org/GNOME/glib/-/issues/1672
race:g_once_impl

Note that accessing a shared variable from multiple threads without synchronization (where at least one access is a write) is always a data race and causes UB.

@dloebl
Copy link
Copy Markdown
Contributor

dloebl commented Mar 31, 2026

That's awesome! Thanks Kleis!
How severe were the TSan findings so far? I'm asking because we still are on libvips v8.16.0 because of #4622

@kleisauke
Copy link
Copy Markdown
Member Author

I think(?) the only severe issue was the one fixed in commit 6967b16 (the code was introduced in v8.16.1), where the eval callback could race with the one in vips_sink_base_progress(). However, this would likely only affect cases where vips_image_set_progress() is enabled and the eval signal is connected via g_signal_connect().

Other than that, the remaining data races involved only flags, which are likely not severe.

@jcupitt
Copy link
Copy Markdown
Member

jcupitt commented Mar 31, 2026

Note that accessing a shared variable from multiple threads without synchronization (where at least one access is a write) is always a data race and causes UB.

libvips does that quite often for events which are not time-critical. Do we need to lock all these, or can we just suppress them?

@kleisauke
Copy link
Copy Markdown
Member Author

Note that accessing a shared variable from multiple threads without synchronization (where at least one access is a write) is always a data race and causes UB.

libvips does that quite often for events which are not time-critical. Do we need to lock all these, or can we just suppress them?

I think this falls under what are referred to as "Benign" data races. This blog post also discusses why such races can still be problematic:
https://bartoszmilewski.com/2020/08/11/benign-data-races-considered-harmful/

I'm aware that GLib uses __ATOMIC_SEQ_CST semantics for its g_atomic API, so it's not using weak atomics. Let me run benchmarks on the previously mentioned changeset using https://github.com/kleisauke/vips-microbench, to see whether it has a measurable impact on performance.

@jcupitt
Copy link
Copy Markdown
Member

jcupitt commented Mar 31, 2026

https://bartoszmilewski.com/2020/08/11/benign-data-races-considered-harmful/

Ah interesting, I guess that's true. Then I suppose we should use glib atomics for these cross-thread "signal" variables.

It'd be good to avoid mutexes or cond vars if possible, they can limit SMP scaling.

Ensure it corresponds to the image passed to `vips_sink_disc()`.

This fixes a regression introduced in bbd9207 where eval callbacks
failed to propagate to the image that was originally marked with
`vips_image_set_progress()`.
This reverts commit 6967b16,
no longer needed after 8154442.
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.

3 participants