Skip to content

Commit

Permalink
Fix the race and deadlock in uf-map, refer from uf-dress.
Browse files Browse the repository at this point in the history
  • Loading branch information
zwets committed Jan 26, 2016
1 parent 8847c50 commit 989fc49
Show file tree
Hide file tree
Showing 3 changed files with 46 additions and 8 deletions.
2 changes: 1 addition & 1 deletion uf-bare
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,6 @@ done
# Do the work

awk -b -O -v F="$HDRSFILE" '
NR%2==1 && F { print > "'"$HDRSFILE"'" }
NR%2==1 && F { print > F }
NR%2==0' "$@"

16 changes: 11 additions & 5 deletions uf-dress
Original file line number Diff line number Diff line change
Expand Up @@ -29,18 +29,22 @@ usage_exit() {
echo
echo "Usage: $(basename $0) [OPTIONS] [FILE] ..."
echo
echo " Insert headers to turn bare sequence FILE(s) into valid unfasta. If no FILE or"
echo " FILE is '-' read from standard input. Write unfasta to standard output."
echo " Insert headers to turn bare sequences into valid unfasta. Reads each line from"
echo " each FILE and writes it to standard output preceded by a header line. If no
echo " FILE is present or FILE is '-' read from standard input."
echo
echo " Options"
echo " -r HDRSFILE Optional file to read header lines from. If not specified then"
echo " default headers 'lcl|NUM' will be generated."
echo " -r HDRSFILE Optional file to read header lines from. If not specified or if"
echo " this file has fewer header lines than sequences, then dummy header"
echo " lines are generated for the remaining sequences."
echo
echo " The HDRSFILE could be a file previously written by 'uf-bare', or output from"
echo " the 'uf-hdrs' filter. Tip: use bash process substitution to avoid temp files:"
echo
echo ' $ uf file.fna | uf-bare | ..processing.. | uf-dress -r <(uf file.fna | uf-hdrs)'
echo
echo " See also: 'uf-map' which implements this idiom in a single command."
echo
exit ${1:-1}
}
Expand Down Expand Up @@ -70,7 +74,9 @@ done
# Do the work
awk -b -O -v F="$HDRSFILE" '{
if (F) getline HDR < F; else HDR = ">lcl|" NR
HDR = ""
if (F) getline HDR < F
if (!HDR) HDR = ">lcl|" NR " Dummy header " NR
print HDR
print
}
Expand Down
36 changes: 34 additions & 2 deletions uf-map
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,39 @@ done
OPERATION="$1"
shift

# AWK it
# Do it

awk -b -O "NR%2==1 { print }; NR%2==0 { print | \"$OPERATION\" }"
# FAIL 1: using pipe within awk
# Fails because of race: external operation is buffering its output, so lines do not come out in the right order.
#awk -b -O -v OPER="sh -c '$OPERATION'" '
# NR%2==1 { print }
# NR%2==0 { print | OPER }
# { fflush() }' "$@"

# FAIL 2: using a FIFO between uf-bare and uf-dress
# Fails because of deadlock: uf-bare blocks on FIFO until uf-dress consumes,
# but uf-dress is waiting for standard input before consuming from FIFO.
#FIFO="/tmp/$(basename "$0").$$"
#mkfifo "$FIFO"
#./uf-bare -f -w "$FIFO" | ./uf-dress -r "$FIFO"
#RETVAL=$?
#rm -f $FIFO

# Maybe using paste to pull things together?

# Set pipefail to have the errorcode of the rightmost failing filter (OPERATION)
[ -z "$BASH" ] set +o pipefail

# Make a FIFO to hold the headers and from which paste merges them with OPERATION standard output
FIFO="/tmp/$(basename "$0").$$"
mkfifo "$FIFO"

# Run the pipeline
awk -b -O -v FIFO="$FIFO" 'NR%2==1 { print > FIFO }; NR%2==0' "$@" | $OPERATION | paste -d '\n' "$FIFO" -
RETVAL=$?

# Clean up - @TODO@ set a shell trap, is cleaner
rm -f $FIFO

exit $RETVAL

0 comments on commit 989fc49

Please sign in to comment.