Subject: mv(1) and signals
To: None <email@example.com>
From: None <firstname.lastname@example.org>
Date: 10/17/2006 16:55:33
Today I tried to move a directory across file systems with mv(1).
The source filesystem was ffs; the target was smbfs. The directory
tree had hundreds of large files.
Then I changed my mind and pressed ^C.
I did that because I noticed that it was copying one subtree of
useless information (the .OLD directory). To save time, I deleted
the source files. A moment later, I had an inkling of trouble when
I got messages from mv, which I thought I had already killed with
mv: dat/.OLD/f_company.1.dat.err: No such file or directory
mv: dat/.OLD/f_security.1.asc: No such file or directory
It's not every day I get messages from a dead process....
When I tried to delete the target .OLD directory that mv had
created, I got a permission in error; when I tried to delete it
from the Windows, it said the file [sic] was in use by another
Back in NetBSD, ps(1) told me this:
$ ps | grep mv 13718 p7 D 0:23.08
mv -PRp dat /usr/users/home[...]
Hmm. Those aren't documented options, and I hadn't typed them.
No amount of 'kill -9' had any effect. In fact, process 13718 kept
right on trucking, moving the other files. I saw them appear on
Now, I understand that mv(1) is supposed to be atomic, and I know
from the manpage moving files across filesystems employs magic
under the covers. But think atomic is different from irreversible,
and I think irreversible is suboptimal.
Without looking at the code, I would guess that mv(1) is masking
signals, perhaps in an effort to achieve atomicity. Yet of course
it can't make a non-atomic action (moving a set of files over a
network) atomic, and preventing kill(8) from terminating the task
looks to be more annoying than anything else.
From my reading of the standard
there's no atomic requirement. It says only that errors should be
handled in such a way that either the source or target tree should
be intact (as in, don't delete the source tree until it's been
As far as I can tell, the only effect of my ^C was to prevent
deletion of the source tree. When the process finished, I seemed
to have two complete copies. Sort of an undocumented feature, in
Does anyone else think ^C should kill mv(1), first time, every