Skip to content

libzfs_core: block delivery of SIGUSR1 in send_worker thread - #19098

Merged
behlendorf merged 1 commit into
openzfs:masterfrom
herrhotzenplotz:nsonack/send-progress-bug
Sep 14, 2026
Merged

behlendorf merged 1 commit into
openzfs:masterfrom
herrhotzenplotz:nsonack/send-progress-bug

Conversation

@herrhotzenplotz

Copy link
Copy Markdown
Contributor

Motivation and Context

zfs send -RPv <snapshot-here> does not periodically print progress information on Linux when stdout is not a pipe.

Description

A detailed explanation can be found in the commit message.
The fix is simple: block delivery of SIGUSR1 to the send_worker quirk thread.

I am not sure about the error case when pthread_sigmask returns an error. I suppose that could be improved.

An alternative would be to go through each place in libzfs and libzfs_core and check where threads are created, modify the signal masks to block delivery of USR1 and selectively unblock them in the progress threads again.
Really, that solution is "more correct" but it seems error-prone.

How Has This Been Tested?

I've verified that this change fixes the bug on Debian Trixie w/ kernel 6.12.107+deb13-amd64.
I have not tested this on FreeBSD and/or Illumos since the code path I have changed is only enabled on Linux.
I have test-compiled on FreeBSD.

Types of Changes

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Performance enhancement (non-breaking change which improves efficiency)
  • Code cleanup (non-breaking change which makes code smaller or more readable)
  • Quality assurance (non-breaking change which makes the code more robust against bugs)
  • Breaking change (fix or feature that would cause existing functionality to change)
  • Library ABI change (libzfs, libzfs_core, libnvpair and libzfsbootenv)
  • Documentation (a change to man pages or other documentation)

Checklist

@herrhotzenplotz
herrhotzenplotz force-pushed the nsonack/send-progress-bug branch 2 times, most recently from 21a4fb2 to f096b92 Compare September 11, 2026 09:30

@behlendorf behlendorf left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I agree limiting the fix to send_worker() is the way to go. That fix itself looks good, just one comment on the error handling. Thanks for running this down!

Comment thread lib/libzfs_core/libzfs_core.c Outdated
@behlendorf behlendorf added the Status: Code Review Needed Ready for review and testing label Sep 11, 2026
@herrhotzenplotz
herrhotzenplotz force-pushed the nsonack/send-progress-bug branch from f096b92 to ae86284 Compare September 14, 2026 05:45
This fixes a Linux-specific bug.

3a909fe (libzfs, libzfs_core: send: always write to pipe, 2022-02-21)
introduced a subtle bug where zfs send -RPv would not print status
information periodically anymore when the stdout is redirected to
something that isn't a pipe (e.g. >/dev/null).

This is because the send_worker thread introduced by this commit
is created with an unmodified signal mask from libzfs. When
zfs_send_space is called it creates this thread.  When we request
verbose status information another thread is created which, in
theory, should periodically receive a SIGUSR1 via a POSIX timer.

The main thread blocks USR1 delivery *after* the creation of the
progress thread, leaving the send_worker thread's signal mask
unmodified. The delivery of SIGUSR1 is now random and for at least
Debian Trixie with kernel 6.12.107+deb13-amd64 this causes the
send_worker to be favoured.

Interestingly, when stracing the zfs send, sometimes delivery flaps
over to the correct thread. Without tracing this doesn't happen and
the output remains silent instead.

Fix this by blocking delivery of SIGUSR1 in the send_worker thread.
We don't need to take care of SIGINFO since this thread is only
created on Linux and SIGINFO is a BSD-specific signal.

Signed-off-by: Nico Sonack <nsonack@herrhotzenplotz.de>
@herrhotzenplotz
herrhotzenplotz force-pushed the nsonack/send-progress-bug branch from ae86284 to f7d8edb Compare September 14, 2026 05:48
@behlendorf behlendorf added Status: Accepted Ready to integrate (reviewed, tested) and removed Status: Code Review Needed Ready for review and testing labels Sep 14, 2026
@behlendorf
behlendorf merged commit c69f0e3 into openzfs:master Sep 14, 2026
43 of 47 checks passed
@herrhotzenplotz
herrhotzenplotz deleted the nsonack/send-progress-bug branch September 15, 2026 04:32
lundman pushed a commit to openzfsonwindows/openzfs that referenced this pull request Sep 27, 2026
This fixes a Linux-specific bug.

3a909fe (libzfs, libzfs_core: send: always write to pipe, 2022-02-21)
introduced a subtle bug where zfs send -RPv would not print status
information periodically anymore when the stdout is redirected to
something that isn't a pipe (e.g. >/dev/null).

This is because the send_worker thread introduced by this commit
is created with an unmodified signal mask from libzfs. When
zfs_send_space is called it creates this thread.  When we request
verbose status information another thread is created which, in
theory, should periodically receive a SIGUSR1 via a POSIX timer.

The main thread blocks USR1 delivery *after* the creation of the
progress thread, leaving the send_worker thread's signal mask
unmodified. The delivery of SIGUSR1 is now random and for at least
Debian Trixie with kernel 6.12.107+deb13-amd64 this causes the
send_worker to be favoured.

Interestingly, when stracing the zfs send, sometimes delivery flaps
over to the correct thread. Without tracing this doesn't happen and
the output remains silent instead.

Fix this by blocking delivery of SIGUSR1 in the send_worker thread.
We don't need to take care of SIGINFO since this thread is only
created on Linux and SIGINFO is a BSD-specific signal.

Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov>
Signed-off-by: Nico Sonack <nsonack@herrhotzenplotz.de>
Closes openzfs#19098
behlendorf pushed a commit that referenced this pull request Sep 28, 2026
This fixes a Linux-specific bug.

3a909fe (libzfs, libzfs_core: send: always write to pipe, 2022-02-21)
introduced a subtle bug where zfs send -RPv would not print status
information periodically anymore when the stdout is redirected to
something that isn't a pipe (e.g. >/dev/null).

This is because the send_worker thread introduced by this commit
is created with an unmodified signal mask from libzfs. When
zfs_send_space is called it creates this thread.  When we request
verbose status information another thread is created which, in
theory, should periodically receive a SIGUSR1 via a POSIX timer.

The main thread blocks USR1 delivery *after* the creation of the
progress thread, leaving the send_worker thread's signal mask
unmodified. The delivery of SIGUSR1 is now random and for at least
Debian Trixie with kernel 6.12.107+deb13-amd64 this causes the
send_worker to be favoured.

Interestingly, when stracing the zfs send, sometimes delivery flaps
over to the correct thread. Without tracing this doesn't happen and
the output remains silent instead.

Fix this by blocking delivery of SIGUSR1 in the send_worker thread.
We don't need to take care of SIGINFO since this thread is only
created on Linux and SIGINFO is a BSD-specific signal.

Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov>
Signed-off-by: Nico Sonack <nsonack@herrhotzenplotz.de>
Closes #19098
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Status: Accepted Ready to integrate (reviewed, tested)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants