Question

J'ai deux programmes shell qui parlent sur un canal nommé. Le lecteur crée le tuyau quand il commence et le supprime quand il se ferme.

Parfois, le rédacteur tente d’écrire dans le tuyau entre le moment où le lecteur arrête de lire et le moment où il supprime le tuyau.

reader: while condition; do read data <$PIPE; do_stuff; done
writer: echo $data >>$PIPE
reader: rm $PIPE

Lorsque cela se produit, l'auteur bloque pour toujours en essayant d'ouvrir le canal pour l'écriture.

Existe-t-il un moyen propre de lui attribuer un délai d'expiration afin qu'il ne reste pas bloqué tant qu'il n'est pas tué manuellement? Je sais que je peux faire

#!/bin/sh
# timed_write <timeout> <file> <args>
# like "echo <args> >> <file>" with a timeout

TIMEOUT=$1
shift;
FILENAME=$1
shift;
PID=$

(X=0; # don't do "sleep $TIMEOUT", the "kill %1" doesn't kill the sleep
 while [ "$X" -lt "$TIMEOUT" ];
 do sleep 1; X=$(expr $X + 1);
 done; kill $PID) &

echo "$@" >>$FILENAME
kill %1

mais c'est un peu dégueulasse. Existe-t-il un shell intégré ou une commande permettant de le faire plus proprement (sans casser le compilateur C)?

Était-ce utile?

La solution 3

Cette paire de programmes fonctionne beaucoup mieux après avoir été ré-écrite en Perl en utilisant des sockets de domaine Unix au lieu de canaux nommés. Le problème particulier de cette question a complètement disparu, car si / quand une extrémité meurt, la connexion disparaîtra au lieu d'être suspendue.

Autres conseils

UNIX " standard " Pour résoudre ce problème, utilisez Expect , qui est fourni avec l'exemple timed-run: exécutez un programme uniquement un laps de temps donné.

Expect peut faire des merveilles pour l’écriture de scripts et en vaut la peine. Si vous n'aimez pas Tcl, il existe également un module Python Expect .

Cette question revient périodiquement (bien que je ne puisse pas la trouver avec une recherche). J'ai écrit deux scripts shell à utiliser comme commandes de délai d'attente: l'un pour les éléments qui lisent l'entrée standard et l'autre pour les éléments qui ne lisent pas l'entrée standard. Cela pue, et je voulais écrire un programme en C, mais je ne l’ai pas encore fait. Je recommanderais certainement d'écrire une fois pour toutes une commande timeout en C. Mais en attendant, voici le plus simple des deux scripts shell, qui se bloque si la commande lit une entrée standard:

#!/bin/ksh

# our watchdog timeout in seconds
maxseconds="$1"
shift

case $# in
  0) echo "Usage: `basename <*>` <seconds> <command> [arg ...]" 1>&2 ;;
esac

"$@" &
waitforpid=$!

{
    sleep $maxseconds
    echo "TIMED OUT: $@" 1>&2 
    2>/dev/null kill -0 $waitforpid && kill -15 $waitforpid
} &
killerpid=$!

>>/dev/null 2>&1 wait $waitforpid
# this is the exit value we care about, so save it and use it when we
rc=$?

# zap our watchdog if it's still there, since we no longer need it
2>>/dev/null kill -0 $killerpid && kill -15 $killerpid

exit $rc

L'autre script est en ligne à l'adresse http: //www.cs.tufts. edu / ~ nr / drop / timeout .

trap 'kill $(ps -L $! -o pid=); exit 30' 30
echo kill -30 $ 2\>/dev/null | at $1 2>/dev/null
shift; eval $@ &
wait
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top