mv(1) atomique ?

Le
xavier
Bonjour,

Puis-je compter sur l'atomicité de mv(1) ou de rename(2) ce qui revient
au même ? La norme POSIX n'est pas claire à ce sujet et les manpages
(FreeBSD) n'en disent rien.

Le problème : un script reçoit des trucs sur son entrée standard, les
traite et produit un fichier. Un autre processus (Perl) va lire ces
fichiers. Il ne connaît rien du script.

Le script de traitement est du genre

cd $WORKDIR || exit 1
cat > tmp.$$
traite tmp.$$
mv tmp.$$ result.$(date '+%s').$$

(je sais que la génération de nom unique n'est pas parfaite, mais je
n'en vois pas d'autre, mktemp crée le fichier, ce qui me fait évidemment
perdre l'atomicité)

Bref, suis-je supposé de poser un lock à la création de ce fichier afin
que le processus traitant les résultats ne risque pas de race
condition ? (j'utiliserais le lockfile de procmail, qui est bien
pratique, et ne semble pas incompatible avec le module Lockfile de Perl)

Merci,

--
XAv
Disponible au 01/06/2010
<http://www.xavierhumbert.net/perso/CV2.html>
Vidéos High-Tech et Jeu Vidéo
Téléchargements
Vos réponses
Gagnez chaque mois un abonnement Premium avec GNT : Inscrivez-vous !
Trier par : date / pertinence
JKB
Le #20995651
Le 17-01-2010, ? propos de
mv(1) atomique ?,
Xavier ?crivait dans fr.comp.os.unix :
Bonjour,

Puis-je compter sur l'atomicité de mv(1) ou de rename(2) ce qui revient
au même ? La norme POSIX n'est pas claire à ce sujet et les manpages
(FreeBSD) n'en disent rien.

Le problème : un script reçoit des trucs sur son entrée standard, les
traite et produit un fichier. Un autre processus (Perl) va lire ces
fichiers. Il ne connaît rien du script.

Le script de traitement est du genre

cd $WORKDIR || exit 1
cat > tmp.$$
traite tmp.$$
mv tmp.$$ result.$(date '+%s').$$

(je sais que la génération de nom unique n'est pas parfaite, mais je
n'en vois pas d'autre, mktemp crée le fichier, ce qui me fait évidemment
perdre l'atomicité)

Bref, suis-je supposé de poser un lock à la création de ce fichier afin
que le processus traitant les résultats ne risque pas de race
condition ? (j'utiliserais le lockfile de procmail, qui est bien
pratique, et ne semble pas incompatible avec le module Lockfile de Perl)

Merci,



Bonsoir,

Je viens de regarder les sources de NetBSD 5 et mv n'a aucune
raison au moins sur ce système d'être atomique. Il copie par bloc
sans mettre de verrou.

Cordialement,

JKB

--
Le cerveau, c'est un véritable scandale écologique. Il représente 2% de notre
masse corporelle, mais disperse à lui seul 25% de l'énergie que nous
consommons tous les jours.
Nicolas George
Le #20995851
JKB wrote in message
Je viens de regarder les sources de NetBSD 5 et mv n'a aucune
raison au moins sur ce système d'être atomique. Il copie par bloc
sans mettre de verrou.



Ça m'étonnerait que mv copie quoi que ce soit quand c'est sur le même
filesystem. Tu ne dois pas avoir les yeux en face des trous.
Cyrille Lefevre
Le #20997341
Xavier a écrit :
Bonjour,

Puis-je compter sur l'atomicité de mv(1) ou de rename(2) ce qui revie nt
au même ? La norme POSIX n'est pas claire à ce sujet et les manpage s
(FreeBSD) n'en disent rien.



Bonjour,

rename peut être "atomic" ou non, ça dépend de l'os, voir même de sa
version.

de mémoire, sous freebsd par ex., cela ne fait pas si longtemps que
rename est "atomic", mais je peux me tromper.

mv peut utiliser rename, mais ce n'est pas garanti non plus !

je ne parle même pas de la couche nfs, la aussi, ça dépend de l'os et de
la version de nfs, de l'implémentation des locks, etc.

hormis nfs, rien de mieux qu'un bon vieux ln (sans -f) old new && rm old

Le problème : un script reçoit des trucs sur son entrée standard, les
traite et produit un fichier. Un autre processus (Perl) va lire ces
fichiers. Il ne connaît rien du script.

Le script de traitement est du genre

cd $WORKDIR || exit 1
cat > tmp.$$
traite tmp.$$
mv tmp.$$ result.$(date '+%s').$$

(je sais que la génération de nom unique n'est pas parfaite, mais j e
n'en vois pas d'autre, mktemp crée le fichier, ce qui me fait évide mment
perdre l'atomicité)



pourquoi ? au contraire, c'est dans les versions de mktemp qui ne créen t
pas le fichier qu'il y a un pb, non ?

Bref, suis-je supposé de poser un lock à la création de ce fichie r afin
que le processus traitant les résultats ne risque pas de race
condition ? (j'utiliserais le lockfile de procmail, qui est bien
pratique, et ne semble pas incompatible avec le module Lockfile de Perl )



pour la génération des locks, j'utilise qqc comme ça :

si timeout < 0, lock bloquant
si timeout == 0, 1 tentative uniquement
si timeout > 0, plusieurs tentatives espacés de sleeptime à concurren ce
de timeout secondes
si sleeptime == "", sleeptime = en fonction de timeout
PS : tiens, il y a un bug, il faut que je teste si sleeptime == 0

trace() { echo trace=; }
PROGNAME=${0##*/}
DEVNULL2= # _devnull2
# function _devnull2 { : je ne vais pas tout te donner non plus; }
_VARTMP=/var/tmp
_TOUCH=touch
_LN=ln
_RM=rm

function _lock # file...
{
set +x; eval $(trace -q _lock "$@")
typeset file=$1 timeout=$2 sleeptime=$3
typeset dir="${TMPDIR:-${_VARTMP}}"
if [[ -z ${file} ]]; then
file="${dir}/${PROGNAME}"
elif [[ ${file} != *'/'* ]]; then
file="${dir}/${file}"
fi
if [[ -z ${timeout} ]]; then
timeout="${TIMEOUT_LOCK_GLOBAL:-60}"
fi
if [[ -z ${sleeptime} ]]; then
if (( timeout > 10 )); then
sleeptime
elif (( timeout < 0 )); then
sleeptime=5
else
sleeptime=1
fi
fi
typeset lock="${file}.lck" temp="${file}.$$"
${_TOUCH} "${temp}"
integer rc=$?
if (( rc == 0 )); then
integer time0="${SECONDS}"
(( time0 -= 1 ))
until ${DEVNULL2} ${_LN} "${temp}" "${lock}"; do
if (( timeout == 0 ||
( timeout > 0 &&
( SECONDS - time0 ) > timeout ) )); then
rc=1
break
fi
sleep "${sleeptime}"
done
${_RM} -f "${temp}"
fi
set +x; eval ${trace}
return ${rc}
}

Cordialement,

Cyrille Lefevre.
--
mailto:Cyrille.Lefevre-news%
supprimer "%nospam% et ".invalid" pour me repondre.
JKB
Le #20998141
Le 17-01-2010, ? propos de
Re: mv(1) atomique ?,
Nicolas George ?crivait dans fr.comp.os.unix :
JKB wrote in message
Je viens de regarder les sources de NetBSD 5 et mv n'a aucune
raison au moins sur ce système d'être atomique. Il copie par bloc
sans mettre de verrou.



Ça m'étonnerait que mv copie quoi que ce soit quand c'est sur le même
filesystem. Tu ne dois pas avoir les yeux en face des trous.



Raconte ce que tu veux. À partir du moment où il y a un cas de non
atomicité, il n'y a aucune garantie sur l'atomicité de mv.

JKB

--
Le cerveau, c'est un véritable scandale écologique. Il représente 2% de notre
masse corporelle, mais disperse à lui seul 25% de l'énergie que nous
consommons tous les jours.
Nicolas George
Le #21001341
JKB wrote in message
Raconte ce que tu veux. À partir du moment où il y a un cas de non
atomicité, il n'y a aucune garantie sur l'atomicité de mv.



Si ce cas est prévisible, alors il suffit de se placer dans le
complémentaire pour avoir exactement la garantie qu'on veut.
Nicolas George
Le #21001331
Cyrille Lefevre wrote in message
rename peut être "atomic" ou non, ça dépend de l'os, voir même de sa
version.



« In this case, a link named new shall remain visible to other processes
throughout the renaming operation and refer either to the file referred to
by new or old before the operation began. »

Si c'est un Unix, rename doit être atomique.

mv peut utiliser rename, mais ce n'est pas garanti non plus !



« The mv utility shall perform actions equivalent to the rename() function
defined in the System Interfaces volume of IEEE Std 1003.1-2001 »
Stephane CHAZELAS
Le #21008961
2010-01-17, 20:29(+01), Xavier:
Bonjour,

Puis-je compter sur l'atomicité de mv(1) ou de rename(2) ce qui revient
au même ? La norme POSIX n'est pas claire à ce sujet et les manpages
(FreeBSD) n'en disent rien.

Le problème : un script reçoit des trucs sur son entrée standard, les
traite et produit un fichier. Un autre processus (Perl) va lire ces
fichiers. Il ne connaît rien du script.

Le script de traitement est du genre

cd $WORKDIR || exit 1
cat > tmp.$$
traite tmp.$$
mv tmp.$$ result.$(date '+%s').$$

(je sais que la génération de nom unique n'est pas parfaite, mais je
n'en vois pas d'autre, mktemp crée le fichier, ce qui me fait évidemment
perdre l'atomicité)


[...]

Si la question est: "est-ce qu'il se peut que result.xxxxx soit
a moitié plein si on l'ouvre au mauvais moment?". La reponse est
non. Ici, on est dans le meme repertoire, donc mv fera un
rename(2), qui consiste just a changer le nom du fichier dans le
repertoire courant. Il ne touche en aucune facon au contenu du
fichier. Il ne touche a l'inode que pour changer le ctime.

La seule question d'atomicité qu'il peut y avoir, c'est: comme
rename(a, b) est fonctionnelement equivalent a link(a,b) &&
unlink(a), s'il n'y avait pas guarantie d'atomicité, et si deux
process faisait un rename au meme moment, (genre rename(a,b) et
rename(a,c)), on pourrait arriver a:

link(a,b)
link(a,c)
unlink(a);
unlink(a) -> fail.

donc se retrouver avec 2 links sur le fichier. Mais je n'ai pas
l'impression que ce soit ton probleme.

--
Stéphane
Publicité
Poster une réponse
Anonyme