[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