[Swift-commit] r4019 - in SwiftApps/SwiftR/Swift: R exec
noreply at svn.ci.uchicago.edu
noreply at svn.ci.uchicago.edu
Thu Jan 20 15:31:55 CST 2011
Author: tga
Date: 2011-01-20 15:31:55 -0600 (Thu, 20 Jan 2011)
New Revision: 4019
Added:
SwiftApps/SwiftR/Swift/R/Fifo.R
SwiftApps/SwiftR/Swift/exec/fiforead
SwiftApps/SwiftR/Swift/exec/fifowrite
Log:
Fixed issues with non-blocking fifos:
* fiforead now returns immediately on success: bug before meant that open file descriptors prevented R system call from returning.
* messages in fiforead now properly quoted so newlines, etc are preserved
Added: SwiftApps/SwiftR/Swift/R/Fifo.R
===================================================================
--- SwiftApps/SwiftR/Swift/R/Fifo.R (rev 0)
+++ SwiftApps/SwiftR/Swift/R/Fifo.R 2011-01-20 21:31:55 UTC (rev 4019)
@@ -0,0 +1,60 @@
+# An R module for non-blocking fifo operations.
+
+.checkFifoArgs <- function(fifopath, timeout) {
+ # Catch errors proactively
+ tryCatch(
+ timeout <- round(timeout),
+ error = function (e) {
+ stop(paste("Provided timeout value of", timeout, "is not numeric"))
+ }
+ )
+
+ if (! file.exists(fifopath) ) {
+ stop(paste("fifo specified does not exist or has wrong permissions:",
+ fifopath))
+ }
+}
+
+
+# writes to a fifo with the provided timeout value
+# if the timeout is exceeded, FALSE is returned
+# otherwise TRUE is returned
+writeFifo <- function (fifopath, message, timeout=3000) {
+ .checkFifoArgs(fifopath, timeout)
+ bin <- file.path(.find.package("Swift"), "exec/fifowrite")
+ cmdString <- paste(bin, fifopath, "-t", timeout,
+ "-m", paste("'", message, "'", sep=""), "&>/dev/null")
+
+ retval <- system(cmdString, wait=TRUE)
+
+ return (retval == 0)
+}
+
+# reads from a fifo with the provided timeout value
+# if the timeout is exceeded, NA is returned
+# otherwise a vector of the lines of text is
+# read from the fifo
+# timeout is in milliseconds.
+readFifo <- function (fifopath, timeout=3000) {
+ .checkFifoArgs(fifopath, timeout)
+ # TODO: fork off another process to do reading, to avoid
+ # the R process blocking irrecoverably
+ # fiforeadln will try to read whatever is available in the fifo, but
+ # if the timeout is exceeded, terminates and writes
+ # _FIFOTIMEOUT_ to stdout
+ bin <- file.path(.find.package("Swift"), "exec/fiforead")
+ cmdString <- paste(bin, fifopath, "-t", timeout)
+ fifodata <- suppressWarnings(system(cmdString, intern=TRUE, ignore.stderr=TRUE))
+ # stderr is ignored as we will get all relevant information
+ # through stdout
+ # want to suppress warning message about exit codea
+ toutMsg <- "_FIFOTIMEOUT_"
+ if (length(fifodata) == 1
+ && substr(fifodata[[1]], 1,nchar(toutMsg)) == toutMsg) {
+ return (NA)
+ }
+ else {
+ return (fifodata)
+ }
+
+}
Added: SwiftApps/SwiftR/Swift/exec/fiforead
===================================================================
--- SwiftApps/SwiftR/Swift/exec/fiforead (rev 0)
+++ SwiftApps/SwiftR/Swift/exec/fiforead 2011-01-20 21:31:55 UTC (rev 4019)
@@ -0,0 +1,70 @@
+#!/bin/sh
+# Read contents of a fifo with a timeout
+# If reading from a fifo fails within timeout specified
+# with -t option in milliseconds then the message _FIFOTIMEOUT_ with
+# a trailing newline is echoed to stdout and no more reading occurs.
+# The program also returns with exit code 2 in this instance.
+# If some data was read from the fifo, and the process subsequently blocks
+# waiting for data, the data will be lost.
+
+fifo=$1
+shift
+timeout=0
+while getopts "t:" OPT
+do
+ case $OPT in
+ t)
+ if [ $OPTARG -eq $OPTARG ]; then
+ timeout=$OPTARG
+ else
+ echo "$timeout" is not an integer
+ exit 1
+ fi ;;
+ \?)
+ echo "Invalid option: $OPTARG" ;;
+ esac
+done
+outfile=`mktemp`
+
+# fork off a process to read from fifo and write to
+# temp file
+cat $fifo &> "$outfile" &
+catpid=$!
+tout_pid=""
+if [ "$timeout" -gt 0 ];
+then
+ stimeout=`echo "scale=3; $timeout/1000.0" | bc`
+ # fork subshell to terminate process
+ (sleep "$stimeout"
+ # Make sure we bring sleep down with self
+ if [ 1 -eq `ps h --pid $catpid | wc -l` ]
+ then
+ # timeout exceeded, kill processes
+ kill -15 $catpid
+ fi
+ )&>/dev/null &
+ # Send output to dev/null so that file descriptors are closed
+ # otherwise R system(... intern=TRUE) call will wait unil fds
+ # are closed
+ tout_pid=$!
+fi
+# ignore kill signal when child is killed:
+# at that time wait will wake up and we can exit normally
+trap "" 15
+if wait $catpid
+then
+ # cat exited normally
+ if [ ! "$tout_pid" = "" ]; then
+ # stop timeout process from lingering
+ kill $tout_pid &> /dev/null
+ fi
+ # Print output
+ cat "$outfile"
+ rm "$outfile"
+ exit 0
+else
+ echo "_FIFOTIMEOUT_"
+ rm "$outfile"
+ #TODO: kill timeout thread
+ exit 2
+fi
Property changes on: SwiftApps/SwiftR/Swift/exec/fiforead
___________________________________________________________________
Name: svn:executable
+ *
Added: SwiftApps/SwiftR/Swift/exec/fifowrite
===================================================================
--- SwiftApps/SwiftR/Swift/exec/fifowrite (rev 0)
+++ SwiftApps/SwiftR/Swift/exec/fifowrite 2011-01-20 21:31:55 UTC (rev 4019)
@@ -0,0 +1,61 @@
+#!/bin/sh
+# Write to a fifo with a timeout, with the data specified by the -m option
+# If writing from a fifo is blocked after timeout specified
+# with -t option in milliseconds then this script exits with code 2.
+# Note that if timeout occurs the data might be partially written to fifo
+
+fifo=$1
+shift
+timeout=0
+msg=""
+
+while getopts "t:m:" OPT
+do
+ case $OPT in
+ m)
+ msg="$OPTARG";;
+ t)
+ if [ $OPTARG -eq $OPTARG ]; then
+ timeout=$OPTARG
+ else
+ echo "$timeout" is not an integer
+ exit 1
+ fi ;;
+ \?)
+ echo "Invalid option: $OPTARG" ;;
+ esac
+done
+
+# fork off a process to read from fifo and write to
+# temp file.
+# Cat reads from stdin and writes to fifo
+echo "$msg" > "$fifo" &
+catpid=$!
+tout_pid=""
+if [ "$timeout" -gt 0 ];
+then
+ stimeout=`echo "scale=3; $timeout/1000.0" | bc`
+ # fork subshell to terminate process
+ (sleep "$stimeout";
+ if [ 1 -eq `ps h --pid $catpid | wc -l` ]
+ then
+ # timeout exceeded, kill processes
+ kill -15 $catpid
+ fi
+ ) &> /dev/null &
+ tout_pid=$!
+fi
+# ignore kill signal when child is killed:
+# at that time wait will wake up and we can exit normally
+trap "" 15
+if wait $catpid
+then
+ # cat exited normally
+ if [ ! "$tout_pid" = "" ]; then
+ # stop timeout process from lingering
+ kill $tout_pid &> /dev/null
+ fi
+ exit 0
+else
+ exit 2
+fi
Property changes on: SwiftApps/SwiftR/Swift/exec/fifowrite
___________________________________________________________________
Name: svn:executable
+ *
More information about the Swift-commit
mailing list