Technically, the behaviour of sync(2) is not a bug. Its job is to
make sure data gets written to disk -- and it does that, barring disk
failures, by scheduling the writes to be done.
It might be nice to have the semantics you propose, but this is not as
simple as it might seem. Keep in mind that there may be other
processes continuing to write data out even while sync(2) is running.
In the general case, in order to prevent sync(2) from being stalled
forever, you would have to introduce a boundary into the sequence of
buffers to be written, and wake up sync(2) when that boundary is
reached. (Similar semantics would also be good for fsync(2).)