pv cannot be started in background.
As you can see in the src/main/main.c file from pv's source code, they're
setting the TOSTOP flag on the terminal with tcsetattr() (in the c.c_lflag of the termios structure). They're doing that in order to receive a SIGTTOU when trying to write to the terminal when not in foreground, catch it with a signal handler, and redirect the output to /dev/null in order not to "mess up" the terminal.
/*
* Set terminal option TOSTOP so we get signal SIGTTOU if we try to
* write to the terminal while backgrounded.
*
* Also, save the current terminal attributes for later restoration.
*/
memset(&t, 0, sizeof(t));
tcgetattr(STDERR_FILENO, &t);
t_save = t;
t.c_lflag |= TOSTOP;
tcsetattr(STDERR_FILENO, TCSANOW, &t);
This is of course gross, because it doesn't set that flag just for itself, but for all the programs using the terminal.
But that's not all. As explained in the glibc manual:
Function: int tcsetattr (int filedes, int when, const struct termios
*termios-p)
If this function is called from a background process on its
controlling terminal, normally all processes in the process group are
sent a SIGTTOU signal, in the same way as if the process were trying
to write to the terminal. The exception is if the calling process
itself is ignoring or blocking SIGTTOU signals, in which case the
operation is performed and no signal is sent. See Job Control.
They're not blocking or ignoring the SIGTTOU. And they're also not checking the return value of tcsetattr() (which would return -1 and set errno to EINTR if they had set the SIGTTOU signal handler before).
So the process is stopped. If it receives a SIGCONT (as from the bg command), it will stop again when trying to complete the tcsetattr().
So I guess you should consider it a feature ;-)