diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/REngine.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/REngine.java
index f52c8e64823a2448a5245895889ef20965acb89f..69d387f4296dabcfd29c30a66dfddbfad7550eeb 100644
--- a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/REngine.java
+++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/REngine.java
@@ -48,6 +48,7 @@ import com.oracle.truffle.r.parser.ast.*;
 import com.oracle.truffle.r.runtime.*;
 import com.oracle.truffle.r.runtime.RContext.ConsoleHandler;
 import com.oracle.truffle.r.runtime.Utils.DebugExitException;
+import com.oracle.truffle.r.runtime.conn.*;
 import com.oracle.truffle.r.runtime.data.*;
 import com.oracle.truffle.r.runtime.data.RPromise.Closure;
 import com.oracle.truffle.r.runtime.data.model.*;
@@ -113,6 +114,7 @@ public final class REngine implements RContext.Engine {
             singleton.crashOnFatalError = crashOnFatalErrorArg;
             singleton.builtinLookup = RBuiltinPackages.getInstance();
             singleton.context = RContext.setRuntimeState(singleton, commandArgs, consoleHandler, new RASTHelperImpl(), headless);
+            StdConnections.initialize();
             MaterializedFrame baseFrame = RRuntime.createNonFunctionFrame().materialize();
             REnvironment.baseInitialize(globalFrame, baseFrame);
             loadBase = FastROptions.LoadBase.getValue();
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/utils/CountFields.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/utils/CountFields.java
index a7eb66db54f3c6f1bdb23ec98b11e866a387058c..8377d68b63e9d5191bbf6eff6b44127fecc2341f 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/utils/CountFields.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/utils/CountFields.java
@@ -44,15 +44,6 @@ public class CountFields {
         byte[] convbuf = new byte[100];
         InputStream is;
 
-        private void checkClose() {
-            if (wasopen) {
-                try {
-                    con.close();
-                } catch (IOException ex) {
-                    // Ignore
-                }
-            }
-        }
     }
 
     @TruffleBoundary
@@ -61,7 +52,6 @@ public class CountFields {
         data.sepchar = sepChar;
         data.comchar = comChar;
         data.quoteset = quoteSet;
-        data.is = file.getInputStream();
 
         if (file.isStdin()) {
             data.ttyflag = true;
@@ -70,6 +60,8 @@ public class CountFields {
             data.ttyflag = false;
         }
 
+        data.wasopen = file.isOpen();
+
         data.save = 0;
         int quote = 0;
         int inquote = 0;
@@ -78,90 +70,89 @@ public class CountFields {
         int blocksize = SCAN_BLOCKSIZE;
         int[] ans = new int[blocksize];
 
-        while (true) {
-            int c = scanchar(inquote, data);
-            if (c == R_EOF) {
-                if (nfields != 0) {
-                    ans[nlines] = nfields;
-                } else {
-                    nlines--;
-                }
-                break;
-            } else if (c == '\n') {
-                if (inquote != 0) {
-                    ans[nlines] = RRuntime.INT_NA;
-                    nlines++;
-                } else if (nfields > 0 || !blskip) {
-                    ans[nlines] = nfields;
-                    nlines++;
-                    nfields = 0;
-                    inquote = 0;
-                }
-                if (nlines == blocksize) {
-                    int[] bns = ans;
-                    blocksize = 2 * blocksize;
-                    ans = new int[blocksize];
-                    System.arraycopy(bns, 0, ans, 0, bns.length);
-                }
-                continue;
-            } else if (data.sepchar != 0) {
-                if (nfields == 0)
-                    nfields++;
-                if (inquote != 0 && c == R_EOF) {
-                    data.checkClose();
-                    throw new IllegalStateException("quoted string on line " + inquote + " terminated by EOF");
-                }
-                if (inquote != 0 && c == quote)
-                    inquote = 0;
-                else if (data.quoteset.indexOf(c) > 0) {
-                    inquote = nlines + 1;
-                    quote = c;
-                }
-                if (c == data.sepchar && inquote == 0)
-                    nfields++;
-            } else if (!Rspace(c)) {
-                if (data.quoteset.indexOf(c) > 0) {
-                    quote = c;
-                    inquote = nlines + 1;
-                    while ((c = scanchar(inquote, data)) != quote) {
-                        if (c == R_EOF) {
-                            data.checkClose();
-                            throw new IllegalStateException("quoted string on line " + inquote + " terminated by EOF");
-                        } else if (c == '\n') {
-                            ans[nlines] = RRuntime.INT_NA;
-                            nlines++;
-                            if (nlines == blocksize) {
-                                int[] bns = ans;
-                                blocksize = 2 * blocksize;
-                                ans = new int[blocksize];
-                                System.arraycopy(bns, 0, ans, 0, bns.length);
+        try (RConnection openConn = file.forceOpen("r")) {
+            data.is = openConn.getInputStream();
+            while (true) {
+                int c = scanchar(inquote, data);
+                if (c == R_EOF) {
+                    if (nfields != 0) {
+                        ans[nlines] = nfields;
+                    } else {
+                        nlines--;
+                    }
+                    break;
+                } else if (c == '\n') {
+                    if (inquote != 0) {
+                        ans[nlines] = RRuntime.INT_NA;
+                        nlines++;
+                    } else if (nfields > 0 || !blskip) {
+                        ans[nlines] = nfields;
+                        nlines++;
+                        nfields = 0;
+                        inquote = 0;
+                    }
+                    if (nlines == blocksize) {
+                        int[] bns = ans;
+                        blocksize = 2 * blocksize;
+                        ans = new int[blocksize];
+                        System.arraycopy(bns, 0, ans, 0, bns.length);
+                    }
+                    continue;
+                } else if (data.sepchar != 0) {
+                    if (nfields == 0)
+                        nfields++;
+                    if (inquote != 0 && c == R_EOF) {
+                        throw new IllegalStateException("quoted string on line " + inquote + " terminated by EOF");
+                    }
+                    if (inquote != 0 && c == quote)
+                        inquote = 0;
+                    else if (data.quoteset.indexOf(c) > 0) {
+                        inquote = nlines + 1;
+                        quote = c;
+                    }
+                    if (c == data.sepchar && inquote == 0)
+                        nfields++;
+                } else if (!Rspace(c)) {
+                    if (data.quoteset.indexOf(c) > 0) {
+                        quote = c;
+                        inquote = nlines + 1;
+                        while ((c = scanchar(inquote, data)) != quote) {
+                            if (c == R_EOF) {
+                                throw new IllegalStateException("quoted string on line " + inquote + " terminated by EOF");
+                            } else if (c == '\n') {
+                                ans[nlines] = RRuntime.INT_NA;
+                                nlines++;
+                                if (nlines == blocksize) {
+                                    int[] bns = ans;
+                                    blocksize = 2 * blocksize;
+                                    ans = new int[blocksize];
+                                    System.arraycopy(bns, 0, ans, 0, bns.length);
+                                }
                             }
                         }
+                        inquote = 0;
+                    } else {
+                        do {
+                            // if (dbcslocale && btowc(c) == WEOF)
+                            // scanchar2(&data);
+                            c = scanchar(0, data);
+                        } while (!Rspace(c) && c != R_EOF);
+                        if (c == R_EOF)
+                            c = '\n';
+                        unscanchar(c, data);
                     }
-                    inquote = 0;
-                } else {
-                    do {
-                        // if (dbcslocale && btowc(c) == WEOF)
-                        // scanchar2(&data);
-                        c = scanchar(0, data);
-                    } while (!Rspace(c) && c != R_EOF);
-                    if (c == R_EOF)
-                        c = '\n';
-                    unscanchar(c, data);
+                    nfields++;
                 }
-                nfields++;
-            }
 
+            }
         }
         /*
          * we might have a character that was unscanchar-ed. So pushback if possible
          */
-        // if (data.save && !data.ttyflag && data.wasopen) {
-        // char line[2] = " ";
-        // line[0] = (char) data.save;
-        // con_pushback(data.con, FALSE, line);
-        // }
-        data.checkClose();
+        if (data.save != 0 && !data.ttyflag && data.wasopen) {
+            // TODO use more primitive method when available
+            file.pushBack(RDataFactory.createStringVectorFromScalar(new String(new char[]{(char) data.save})), false);
+        }
 
         if (nlines < 0) {
             return RNull.instance;
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ConnectionFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ConnectionFunctions.java
index a02a9281f8c01c827a69566db211adaed874cc80..2b2002208256f5a57af5dac192d8469932737930 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ConnectionFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ConnectionFunctions.java
@@ -232,9 +232,9 @@ public abstract class ConnectionFunctions {
             Object[] data = new Object[NAMES.getLength()];
             data[0] = baseCon.getSummaryDescription();
             data[1] = baseCon.getClassHr().getDataAt(0);
-            data[2] = baseCon.getOpenMode().modeString;
+            data[2] = baseCon.getOpenMode().summaryString();
             data[3] = baseCon.getSummaryText();
-            data[4] = baseCon.isClosed() || !baseCon.isOpen() ? "closed" : "opened";
+            data[4] = baseCon.isOpen() ? "opened" : "closed";
             data[5] = baseCon.canRead() ? "yes" : "no";
             data[6] = baseCon.canWrite() ? "yes" : "no";
             return RDataFactory.createList(data, NAMES);
@@ -279,7 +279,7 @@ public abstract class ConnectionFunctions {
         protected RLogicalVector isOpen(RConnection con, RAbstractIntVector rw) {
             controlVisibility();
             BaseRConnection baseCon = getBaseConnection(con);
-            boolean result = !baseCon.isClosed() && baseCon.isOpen();
+            boolean result = baseCon.isOpen();
             switch (rw.getDataAt(0)) {
                 case 0:
                     break;
@@ -311,7 +311,7 @@ public abstract class ConnectionFunctions {
         protected Object close(RConnection con) {
             forceVisibility(false);
             try {
-                con.close();
+                con.closeAndDestroy();
             } catch (IOException ex) {
                 throw RError.error(getEncapsulatingSourceSection(), RError.Message.GENERIC, ex.getMessage());
             }
@@ -334,7 +334,7 @@ public abstract class ConnectionFunctions {
         protected void internalClose(RConnection con) throws RError {
             try {
                 BaseRConnection baseConn = getBaseConnection(con);
-                baseConn.internalClose();
+                baseConn.close();
             } catch (IOException ex) {
                 throw RError.error(getEncapsulatingSourceSection(), RError.Message.GENERIC, ex.getMessage());
             }
@@ -349,20 +349,14 @@ public abstract class ConnectionFunctions {
         protected Object readLines(RConnection con, int n, byte ok, @SuppressWarnings("unused") byte warn, @SuppressWarnings("unused") String encoding, @SuppressWarnings("unused") byte skipNul) {
             // TODO implement all the arguments
             controlVisibility();
-            boolean wasOpen = true;
-            try {
-                wasOpen = con.forceOpen("rt");
-                String[] lines = con.readLines(n);
+            try (RConnection openConn = con.forceOpen("rt")) {
+                String[] lines = openConn.readLines(n);
                 if (n > 0 && lines.length < n && ok == RRuntime.LOGICAL_FALSE) {
                     throw RError.error(getEncapsulatingSourceSection(), RError.Message.TOO_FEW_LINES_READ_LINES);
                 }
                 return RDataFactory.createStringVector(lines, RDataFactory.COMPLETE_VECTOR);
             } catch (IOException x) {
                 throw RError.error(getEncapsulatingSourceSection(), RError.Message.ERROR_READING_CONNECTION, x.getMessage());
-            } finally {
-                if (!wasOpen) {
-                    internalClose(con);
-                }
             }
         }
 
@@ -385,16 +379,10 @@ public abstract class ConnectionFunctions {
         @Specialization
         @TruffleBoundary
         protected RNull writeLines(RAbstractStringVector text, RConnection con, RAbstractStringVector sep, @SuppressWarnings("unused") byte useBytes) {
-            boolean wasOpen = true;
-            try {
-                wasOpen = con.forceOpen("wt");
-                con.writeLines(text, sep.getDataAt(0));
+            try (RConnection openConn = con.forceOpen("wt")) {
+                openConn.writeLines(text, sep.getDataAt(0));
             } catch (IOException x) {
                 throw RError.error(getEncapsulatingSourceSection(), RError.Message.ERROR_WRITING_CONNECTION, x.getMessage());
-            } finally {
-                if (!wasOpen) {
-                    internalClose(con);
-                }
             }
             forceVisibility(false);
             return RNull.instance;
@@ -527,20 +515,14 @@ public abstract class ConnectionFunctions {
         @TruffleBoundary
         protected RStringVector readChar(RConnection con, RAbstractIntVector nchars, RAbstractLogicalVector useBytes) {
             controlVisibility();
-            boolean wasOpen = true;
-            try {
-                wasOpen = con.forceOpen("rb");
+            try (RConnection openConn = con.forceOpen("rb")) {
                 String[] data = new String[nchars.getLength()];
                 for (int i = 0; i < data.length; i++) {
-                    data[i] = con.readChar(nchars.getDataAt(i), useBytes.getDataAt(0) == RRuntime.LOGICAL_TRUE);
+                    data[i] = openConn.readChar(nchars.getDataAt(i), useBytes.getDataAt(0) == RRuntime.LOGICAL_TRUE);
                 }
                 return RDataFactory.createStringVector(data, RDataFactory.COMPLETE_VECTOR);
             } catch (IOException x) {
                 throw RError.error(getEncapsulatingSourceSection(), RError.Message.ERROR_READING_CONNECTION, x.getMessage());
-            } finally {
-                if (!wasOpen) {
-                    internalClose(con);
-                }
             }
         }
 
@@ -561,9 +543,7 @@ public abstract class ConnectionFunctions {
         @Specialization
         protected RNull writeChar(RAbstractStringVector object, RConnection con, RAbstractIntVector nchars, RAbstractStringVector eos, byte useBytes) {
             controlVisibility();
-            boolean wasOpen = true;
-            try {
-                wasOpen = con.forceOpen("wb");
+            try (RConnection openConn = con.forceOpen("wb")) {
                 int length = object.getLength();
                 for (int i = 0; i < length; i++) {
                     String s = object.getDataAt(i);
@@ -572,14 +552,10 @@ public abstract class ConnectionFunctions {
                     if (pad > 0) {
                         RContext.getInstance().setEvalWarning(RError.Message.MORE_CHARACTERS.message);
                     }
-                    con.writeChar(s, pad, eos.getDataAt(i % length), RRuntime.fromLogical(useBytes));
+                    openConn.writeChar(s, pad, eos.getDataAt(i % length), RRuntime.fromLogical(useBytes));
                 }
             } catch (IOException x) {
                 throw RError.error(getEncapsulatingSourceSection(), RError.Message.ERROR_READING_CONNECTION, x.getMessage());
-            } finally {
-                if (!wasOpen) {
-                    internalClose(con);
-                }
             }
             forceVisibility(false);
             return RNull.instance;
@@ -613,14 +589,12 @@ public abstract class ConnectionFunctions {
         @Specialization
         protected Object readBin(RConnection con, RAbstractStringVector whatVec, RAbstractIntVector nVec, int size, byte signedArg, byte swapArg) {
             boolean swap = RRuntime.fromLogical(swapArg);
-            boolean wasOpen = true;
             RVector result = null;
             int n = nVec.getDataAt(0);
-            try {
-                if (getBaseConnection(con).getOpenMode().isText()) {
+            try (RConnection openConn = con.forceOpen("rb")) {
+                if (getBaseConnection(openConn).getOpenMode().isText()) {
                     throw RError.error(getEncapsulatingSourceSection(), RError.Message.ONLY_READ_BINARY_CONNECTION);
                 }
-                wasOpen = con.forceOpen("rb");
                 String what = whatVec.getDataAt(0);
                 switch (what) {
                     case "int":
@@ -648,10 +622,6 @@ public abstract class ConnectionFunctions {
                 }
             } catch (IOException x) {
                 throw RError.error(getEncapsulatingSourceSection(), RError.Message.ERROR_READING_CONNECTION, x.getMessage());
-            } finally {
-                if (!wasOpen) {
-                    internalClose(con);
-                }
             }
             return result;
         }
@@ -782,14 +752,12 @@ public abstract class ConnectionFunctions {
         @Specialization
         protected Object writeBin(RAbstractVector object, RConnection con, int size, byte swapArg, byte useBytesArg) {
             boolean swap = RRuntime.fromLogical(swapArg);
-            boolean wasOpen = true;
             boolean useBytes = RRuntime.fromLogical(useBytesArg);
             if (object.getLength() > 0) {
-                try {
-                    if (getBaseConnection(con).isTextMode()) {
+                try (RConnection openConn = con.forceOpen("wb")) {
+                    if (getBaseConnection(openConn).isTextMode()) {
                         throw RError.error(getEncapsulatingSourceSection(), RError.Message.ONLY_WRITE_BINARY_CONNECTION);
                     }
-                    wasOpen = con.forceOpen("wb");
                     if (object instanceof RAbstractIntVector) {
                         writeInteger((RAbstractIntVector) object, con, size, swap);
                     } else if (object instanceof RAbstractDoubleVector) {
@@ -807,10 +775,6 @@ public abstract class ConnectionFunctions {
                     }
                 } catch (IOException x) {
                     throw RError.error(getEncapsulatingSourceSection(), RError.Message.ERROR_WRITING_CONNECTION, x.getMessage());
-                } finally {
-                    if (!wasOpen) {
-                        internalClose(con);
-                    }
                 }
             }
             forceVisibility(false);
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ForeignFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ForeignFunctions.java
index 6257433b7bf31b5e0e3e00ffe26c857ac6f71c42..f8d2840822b2f2b4fb4f3a0392e09a05c360180e 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ForeignFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ForeignFunctions.java
@@ -742,22 +742,11 @@ public class ForeignFunctions {
                     quoteSet = s;
                 }
             }
-            boolean wasOpen = true;
-            try {
-                wasOpen = conn.forceOpen("r");
-                return CountFields.execute(conn, sepChar, quoteSet, nskip, RRuntime.fromLogical(blskip), comChar);
+            try (RConnection openConn = conn.forceOpen("r")) {
+                return CountFields.execute(openConn, sepChar, quoteSet, nskip, RRuntime.fromLogical(blskip), comChar);
             } catch (IllegalStateException | IOException ex) {
                 errorProfile.enter();
                 throw RError.error(getEncapsulatingSourceSection(), RError.Message.GENERIC, ex.getMessage());
-            } finally {
-                if (!wasOpen) {
-                    try {
-                        conn.internalClose();
-                    } catch (IOException ex) {
-                        errorProfile.enter();
-                        throw RError.error(getEncapsulatingSourceSection(), RError.Message.GENERIC, ex.getMessage());
-                    }
-                }
             }
         }
 
@@ -772,22 +761,11 @@ public class ForeignFunctions {
             Object[] argValues = args.getValues();
             RConnection conn = (RConnection) argValues[0];
             int nlines = castInt(frame, castVector(frame, argValues[1]));
-            boolean wasOpen = true;
-            try {
-                wasOpen = conn.forceOpen("r");
-                return RDataFactory.createStringVector(conn.readLines(nlines), RDataFactory.COMPLETE_VECTOR);
+            try (RConnection openConn = conn.forceOpen("r")) {
+                return RDataFactory.createStringVector(openConn.readLines(nlines), RDataFactory.COMPLETE_VECTOR);
             } catch (IOException ex) {
                 errorProfile.enter();
                 throw RError.error(getEncapsulatingSourceSection(), RError.Message.ERROR_READING_CONNECTION, ex.getMessage());
-            } finally {
-                if (!wasOpen) {
-                    try {
-                        conn.internalClose();
-                    } catch (IOException ex) {
-                        errorProfile.enter();
-                        throw RError.error(getEncapsulatingSourceSection(), RError.Message.GENERIC, ex.getMessage());
-                    }
-                }
             }
         }
 
@@ -921,22 +899,11 @@ public class ForeignFunctions {
                     quoteCol[qi - 1] = true;
                 }
             }
-            boolean wasOpen = true;
-            try {
-                wasOpen = conn.forceOpen("wt");
-                WriteTable.execute(conn, argValues[0], nr, nc, rnamesArg, csep, ceol, cna, cdec.charAt(0), RRuntime.fromLogical(qmethod), quoteCol, quoteRn);
+            try (RConnection openConn = conn.forceOpen("wt")) {
+                WriteTable.execute(openConn, argValues[0], nr, nc, rnamesArg, csep, ceol, cna, cdec.charAt(0), RRuntime.fromLogical(qmethod), quoteCol, quoteRn);
             } catch (IOException | IllegalArgumentException ex) {
                 errorProfile.enter();
                 throw RError.error(getEncapsulatingSourceSection(), RError.Message.GENERIC, ex.getMessage());
-            } finally {
-                if (!wasOpen) {
-                    try {
-                        conn.internalClose();
-                    } catch (IOException ex) {
-                        errorProfile.enter();
-                        throw RError.error(getEncapsulatingSourceSection(), RError.Message.GENERIC, ex.getMessage());
-                    }
-                }
             }
             return RNull.instance;
         }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/LoadFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/LoadFunctions.java
index 0986ea573554a373416d4217564b6c87c90f3a54..6e9e27bb89fdb0b1381d0170d467394c4eed220f 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/LoadFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/LoadFunctions.java
@@ -37,13 +37,8 @@ public class LoadFunctions {
         @Specialization
         protected RStringVector load(VirtualFrame frame, RConnection con, REnvironment envir, @SuppressWarnings("unused") RAbstractLogicalVector verbose) {
             controlVisibility();
-            boolean wasOpen = true;
-            try {
-                /*
-                 * The connection may or may not be open (see load.R).
-                 */
-                wasOpen = con.forceOpen("rb");
-                String s = con.readChar(5, true);
+            try (RConnection openConn = con.forceOpen("r")) {
+                String s = openConn.readChar(5, true);
                 if (s.equals("RDA2\n") || s.equals("RDB2\n") || s.equals("RDX2\n")) {
                     Object o = RSerialize.unserialize(con, RArguments.getDepth(frame));
                     if (!(o instanceof RPairList)) {
@@ -78,14 +73,6 @@ public class LoadFunctions {
                 throw RError.error(getEncapsulatingSourceSection(), RError.Message.ERROR_READING_CONNECTION, iox.getMessage());
             } catch (PutException px) {
                 throw RError.error(this.getEncapsulatingSourceSection(), px);
-            } finally {
-                if (!wasOpen) {
-                    try {
-                        con.internalClose();
-                    } catch (IOException ex) {
-                        throw RError.error(getEncapsulatingSourceSection(), RError.Message.GENERIC, ex.getMessage());
-                    }
-                }
             }
 
         }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ReadDCF.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ReadDCF.java
index 3464754010bf1cb3738065a26baa85eb69c3c72e..29995914dae6e713613116bcc3334e518cac96f1 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ReadDCF.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ReadDCF.java
@@ -47,7 +47,7 @@ public abstract class ReadDCF extends RBuiltinNode {
     @TruffleBoundary
     protected RStringVector doReadDCF(RConnection conn, RAbstractStringVector fields, @SuppressWarnings("unused") RNull keepWhite) {
         DCF dcf = null;
-        try {
+        try (RConnection openConn = conn.forceOpen("r")) {
             dcf = DCF.read(conn.readLines(0));
         } catch (IOException ex) {
             throw RError.error(getEncapsulatingSourceSection(), RError.Message.ERROR_READING_CONNECTION, ex.getMessage());
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/SerializeFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/SerializeFunctions.java
index beb97cee66f0d3dc8adb5d59462e447d34a064fd..84431a25477a1ec03f06fd04a671630bd595bdc8 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/SerializeFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/SerializeFunctions.java
@@ -37,9 +37,6 @@ import com.oracle.truffle.r.runtime.env.*;
 
 public class SerializeFunctions {
 
-    // TODO This code needs to check for unopened connections as per GnuR,
-    // which requires more publicly visible support in RConnection
-
     @RBuiltin(name = "unserializeFromConn", kind = INTERNAL, parameterNames = {"conn", "refhook"})
     public abstract static class UnserializeFromConn extends RInvisibleBuiltinNode {
         @Specialization
@@ -50,24 +47,14 @@ public class SerializeFunctions {
         @TruffleBoundary
         protected Object doUnserializeFromConn(RConnection conn, @SuppressWarnings("unused") REnvironment refhook, int depth) {
             controlVisibility();
-            boolean wasOpen = true;
-            try {
-                wasOpen = conn.forceOpen("rb");
-                if (!conn.canRead()) {
+            try (RConnection openConn = conn.forceOpen("rb")) {
+                if (!openConn.canRead()) {
                     throw RError.error(getEncapsulatingSourceSection(), RError.Message.CONNECTION_NOT_OPEN_READ);
                 }
-                Object result = RSerialize.unserialize(conn, depth);
+                Object result = RSerialize.unserialize(openConn, depth);
                 return result;
             } catch (IOException ex) {
                 throw RError.error(getEncapsulatingSourceSection(), RError.Message.GENERIC, ex.getMessage());
-            } finally {
-                if (!wasOpen) {
-                    try {
-                        conn.internalClose();
-                    } catch (IOException ex) {
-                        throw RError.error(getEncapsulatingSourceSection(), RError.Message.GENERIC, ex.getMessage());
-                    }
-                }
             }
         }
 
@@ -88,28 +75,18 @@ public class SerializeFunctions {
         @TruffleBoundary
         protected Object doSerializeToConn(Object object, RConnection conn, byte asciiLogical, @SuppressWarnings("unused") RNull version, @SuppressWarnings("unused") RNull refhook, int depth) {
             controlVisibility();
-            boolean wasOpen = true;
-            try {
+            try (RConnection openConn = conn.forceOpen("wb")) {
                 boolean ascii = RRuntime.fromLogical(asciiLogical);
-                wasOpen = conn.forceOpen("wb");
-                if (!conn.canWrite()) {
+                if (!openConn.canWrite()) {
                     throw RError.error(getEncapsulatingSourceSection(), RError.Message.CONNECTION_NOT_OPEN_WRITE);
                 }
-                if (!ascii && conn.isTextMode()) {
+                if (!ascii && openConn.isTextMode()) {
                     throw RError.error(getEncapsulatingSourceSection(), RError.Message.BINARY_CONNECTION_REQUIRED);
                 }
-                RSerialize.serialize(conn, object, ascii, 2, null, depth);
+                RSerialize.serialize(openConn, object, ascii, 2, null, depth);
                 return RNull.instance;
             } catch (IOException ex) {
                 throw RError.error(getEncapsulatingSourceSection(), RError.Message.GENERIC, ex.getMessage());
-            } finally {
-                if (!wasOpen) {
-                    try {
-                        conn.internalClose();
-                    } catch (IOException ex) {
-                        throw RError.error(getEncapsulatingSourceSection(), RError.Message.GENERIC, ex.getMessage());
-                    }
-                }
             }
         }
     }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/ConnectionSupport.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/ConnectionSupport.java
index aa1b7646afc5289c93b9af7a7bfe3b3a7d8fdfc7..de6302253f52d6bb85f64159aba835effca5783b 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/ConnectionSupport.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/ConnectionSupport.java
@@ -80,7 +80,7 @@ public class ConnectionSupport {
         ReadAppend(new String[]{"a+"}, true, true, true),
         ReadAppendBinary(new String[]{"a+b"}, false, true, true);
 
-        private String[] modeStrings;
+        public final String[] modeStrings;
         public final boolean isText;
         public final boolean readable;
         public final boolean writeable;
@@ -113,15 +113,34 @@ public class ConnectionSupport {
      */
     public static class OpenMode {
         public final AbstractOpenMode abstractOpenMode;
+        /**
+         * When {@link #abstractOpenMode} is {@code Lazy}, this is used to store the default open
+         * mode, otherwise it is the actual string passed to the open.
+         */
         public final String modeString;
 
-        public OpenMode(String modeString) throws IOException {
-            this(modeString, AbstractOpenMode.getOpenMode(modeString));
+        /**
+         * For connections other than {@link StdConnections}.
+         */
+
+        public OpenMode(String modeString, AbstractOpenMode defaultModeForLazy) throws IOException {
+            this.abstractOpenMode = AbstractOpenMode.getOpenMode(modeString);
+            this.modeString = abstractOpenMode == AbstractOpenMode.Lazy ? defaultModeForLazy.modeStrings[0] : modeString;
         }
 
-        OpenMode(String modeString, AbstractOpenMode mode) {
-            this.modeString = modeString;
-            this.abstractOpenMode = mode;
+        /**
+         * For {@link StdConnections}.
+         */
+        OpenMode(AbstractOpenMode mode) throws IOException {
+            this(mode.modeStrings[0], mode);
+        }
+
+        /**
+         * Only used when a lazy connection is actually opened.
+         */
+        OpenMode(String modeString) throws IOException {
+            // defaultModeForLazy will not be used
+            this(modeString, null);
         }
 
         public boolean isText() {
@@ -135,6 +154,10 @@ public class ConnectionSupport {
         boolean canWrite() {
             return abstractOpenMode.writeable;
         }
+
+        public String summaryString() {
+            return abstractOpenMode == AbstractOpenMode.Lazy ? "" : modeString;
+        }
     }
 
     enum ConnectionClass {
@@ -158,9 +181,10 @@ public class ConnectionSupport {
     /**
      * Class that holds common state for all {@link RConnection} instances. It supports lazy
      * opening, as required by the R spec, through the {@link #theConnection} field, which
-     * ultimately holds the actual connection instance when opened. The default implementations of
-     * the {@link RConnection} methods check whether the connection is open and if not, call
-     * {@link #createDelegateConnection()} and then forward the operation. The result of
+     * ultimately holds the actual connection instance when opened. Any builtin that uses a
+     * connection passed in as argument must call {@link RConnection#forceOpen} to check whether the
+     * connection is already open. If not already open {@link #forceOpen} will call
+     * {@link #createDelegateConnection()} to create the actual connection. The result of
      * {@link #createDelegateConnection()} should be a subclass of {@link DelegateRConnection},
      * which subclasses {@link RConnection} directly. A subclass may choose not to use delegation by
      * overriding the default implementations of the methods in this class. A
@@ -186,12 +210,20 @@ public class ConnectionSupport {
          */
         protected boolean closed;
 
+        /**
+         * Supports the auto-close operation for connections opened just for a single operation.
+         */
+        private boolean tempOpened;
+
         /**
          * if {@link #opened} is {@code true} the {@link OpenMode} that this connection is opened
          * in, otherwise {@link AbstractOpenMode#Lazy}.
          */
         private OpenMode openMode;
 
+        /**
+         * The classes of the connection, which always includes "connection".
+         */
         private final RStringVector classHr;
 
         /**
@@ -199,29 +231,41 @@ public class ConnectionSupport {
          */
         protected DelegateRConnection theConnection;
 
+        /**
+         * An integer used to identify the connection to the {@code getAllConnections} builtin.
+         */
         private int descriptor;
 
         /**
-         * The constructor to use for a connection class whose default open mode is not "read", but
-         * specified explicitly by "lazyMode".
+         * The constructor for every connection class except {@link StdConnections}.
+         *
+         * @param conClass the specific class of the connection, e.g, {@link ConnectionClass#File}
+         * @param modeString the mode in which the connection should be opened, "" for lazy opening
+         * @param defaultModeForLazy the mode to use when this connection is opened implicitly
+         *
+         */
+        protected BaseRConnection(ConnectionClass conClass, String modeString, AbstractOpenMode defaultModeForLazy) throws IOException {
+            this(conClass, new OpenMode(modeString, defaultModeForLazy));
+            setDescriptor(getConnectionIndex());
+        }
+
+        /**
+         * The constructor for {@link StdConnections}.
          */
-        protected BaseRConnection(ConnectionClass conClass, String modeString) throws IOException {
-            this(conClass, new OpenMode(modeString), false);
+        protected BaseRConnection(AbstractOpenMode mode, int index) throws IOException {
+            this(ConnectionClass.Terminal, new OpenMode(mode));
+            setDescriptor(index);
         }
 
         /**
-         * Primitive constructor that just assigns state. Used by {@link StdConnections} as they are
-         * a special case, but should not be used by other connection types.
+         * Primitive constructor that just assigns state.
          */
-        protected BaseRConnection(ConnectionClass conClass, OpenMode mode, boolean std) {
+        private BaseRConnection(ConnectionClass conClass, OpenMode mode) {
             this.openMode = mode;
             String[] classes = new String[2];
             classes[0] = conClass.printName;
             classes[1] = "connection";
             this.classHr = RDataFactory.createStringVector(classes, RDataFactory.COMPLETE_VECTOR);
-            if (!std) {
-                registerConnection();
-            }
         }
 
         protected void openNonLazyConnection() throws IOException {
@@ -233,7 +277,8 @@ public class ConnectionSupport {
         /**
          * A connection is "active" if it has been opened and not yet closed.
          */
-        protected boolean isActive() {
+        @Override
+        public boolean isOpen() {
             return !closed && opened;
         }
 
@@ -242,7 +287,7 @@ public class ConnectionSupport {
          */
         @Override
         public boolean canRead() {
-            if (isActive()) {
+            if (isOpen()) {
                 return getOpenMode().canRead();
             } else {
                 // Might think to check the lazy open mode, but GnuR doesn't
@@ -255,7 +300,7 @@ public class ConnectionSupport {
          */
         @Override
         public boolean canWrite() {
-            if (isActive()) {
+            if (isOpen()) {
                 return getOpenMode().canWrite();
             } else {
                 // Might think to check the lazy open mode, but GnuR doesn't
@@ -271,32 +316,30 @@ public class ConnectionSupport {
             return getOpenMode().isText();
         }
 
-        private void registerConnection() {
+        private static int getConnectionIndex() {
             for (int i = 3; i < allConnections.length; i++) {
                 if (allConnections[i] == null) {
-                    allConnections[i] = this;
-                    descriptor = i;
-                    return;
+                    return i;
                 }
             }
             throw RError.error(RError.Message.ALL_CONNECTIONS_IN_USE);
         }
 
         @Override
-        public boolean forceOpen(String modeString) throws IOException {
-            boolean ret = opened;
+        public RConnection forceOpen(String modeString) throws IOException {
             if (closed) {
                 throw new IOException(RError.Message.INVALID_CONNECTION.message);
             }
             if (!opened) {
+                tempOpened = true;
                 // internal closed or lazy
-                if (getOpenMode().abstractOpenMode == AbstractOpenMode.Lazy) {
+                if (openMode.abstractOpenMode == AbstractOpenMode.Lazy) {
                     // modeString may override the default
-                    openMode = new OpenMode(modeString);
+                    openMode = new OpenMode(modeString == null ? openMode.modeString : modeString);
                 }
                 createDelegateConnection();
             }
-            return ret;
+            return this;
         }
 
         protected void checkOpen() {
@@ -369,22 +412,25 @@ public class ConnectionSupport {
         }
 
         @Override
-        public void close() throws IOException {
+        public void closeAndDestroy() throws IOException {
             closed = true;
             if (theConnection != null) {
-                theConnection.close();
+                theConnection.closeAndDestroy();
             }
             assert allConnections[this.descriptor] != null;
             allConnections[this.descriptor] = null;
         }
 
         @Override
-        public void internalClose() throws IOException {
-            opened = false;
-            if (theConnection != null) {
-                DelegateRConnection tc = theConnection;
-                theConnection = null;
-                tc.internalClose();
+        public void close() throws IOException {
+            if (tempOpened) {
+                tempOpened = false;
+                opened = false;
+                if (theConnection != null) {
+                    DelegateRConnection tc = theConnection;
+                    theConnection = null;
+                    tc.close();
+                }
             }
         }
 
@@ -420,6 +466,12 @@ public class ConnectionSupport {
             return descriptor;
         }
 
+        private void setDescriptor(int index) {
+            assert allConnections[index] == null;
+            this.descriptor = index;
+            allConnections[index] = this;
+        }
+
         public static BaseRConnection getConnection(int descriptor) {
             if (descriptor >= allConnections.length || allConnections[descriptor] == null) {
                 throw RError.error(RError.Message.INVALID_CONNECTION);
@@ -452,10 +504,6 @@ public class ConnectionSupport {
             return classHr;
         }
 
-        public boolean isOpen() {
-            return opened;
-        }
-
         public boolean isClosed() {
             return closed;
         }
@@ -630,7 +678,12 @@ public class ConnectionSupport {
         }
 
         @Override
-        public boolean forceOpen(String modeString) throws IOException {
+        public boolean isOpen() {
+            return base.isOpen();
+        }
+
+        @Override
+        public RConnection forceOpen(String modeString) throws IOException {
             return base.forceOpen(modeString);
         }
 
@@ -739,7 +792,11 @@ public class ConnectionSupport {
         protected final String path;
 
         protected BasePathRConnection(String path, ConnectionClass connectionClass, String modeString) throws IOException {
-            super(connectionClass, modeString);
+            this(path, connectionClass, modeString, AbstractOpenMode.Read);
+        }
+
+        protected BasePathRConnection(String path, ConnectionClass connectionClass, String modeString, AbstractOpenMode defaultLazyOpenMode) throws IOException {
+            super(connectionClass, modeString, defaultLazyOpenMode);
             this.path = Utils.tildeExpand(path);
         }
 
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/FileConnections.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/FileConnections.java
index 9cccbc2b44eba8804ce9d5c393eea7e616776a88..60671f03be917f1941cc984facb31faea3fbfcc0 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/FileConnections.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/FileConnections.java
@@ -105,13 +105,13 @@ public class FileConnections {
         }
 
         @Override
-        public void close() throws IOException {
+        public void closeAndDestroy() throws IOException {
             base.closed = true;
-            internalClose();
+            close();
         }
 
         @Override
-        public void internalClose() throws IOException {
+        public void close() throws IOException {
             inputStream.close();
         }
 
@@ -147,13 +147,13 @@ public class FileConnections {
         }
 
         @Override
-        public void close() throws IOException {
+        public void closeAndDestroy() throws IOException {
             base.closed = true;
-            internalClose();
+            close();
         }
 
         @Override
-        public void internalClose() throws IOException {
+        public void close() throws IOException {
             outputStream.close();
         }
 
@@ -198,13 +198,13 @@ public class FileConnections {
         }
 
         @Override
-        public void close() throws IOException {
+        public void closeAndDestroy() throws IOException {
             base.closed = true;
-            internalClose();
+            close();
         }
 
         @Override
-        public void internalClose() throws IOException {
+        public void close() throws IOException {
             inputStream.close();
         }
 
@@ -234,13 +234,13 @@ public class FileConnections {
         }
 
         @Override
-        public void close() throws IOException {
+        public void closeAndDestroy() throws IOException {
             base.closed = true;
-            internalClose();
+            close();
         }
 
         @Override
-        public void internalClose() throws IOException {
+        public void close() throws IOException {
             flush();
             outputStream.close();
         }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/GZIPConnections.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/GZIPConnections.java
index a1b57699f483c755e1eaf6e6b30f637cb7ab85b1..b22b9c321de14927cb7d05d87e43b82fca931fbc 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/GZIPConnections.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/GZIPConnections.java
@@ -33,12 +33,14 @@ import com.oracle.truffle.r.runtime.*;
 import com.oracle.truffle.r.runtime.data.model.*;
 
 public class GZIPConnections {
+    private static final int GZIP_BUFFER_SIZE = (2 << 20);
+
     /**
      * Base class for all modes of gzfile connections.
      */
     public static class GZIPRConnection extends BasePathRConnection {
         public GZIPRConnection(String path, String modeString) throws IOException {
-            super(path, ConnectionClass.GZFile, modeString);
+            super(path, ConnectionClass.GZFile, modeString, AbstractOpenMode.ReadBinary);
             openNonLazyConnection();
         }
 
@@ -70,7 +72,7 @@ public class GZIPConnections {
 
         GZIPInputRConnection(GZIPRConnection base) throws IOException {
             super(base);
-            inputStream = new GZIPInputStream(new FileInputStream(base.path), RConnection.GZIP_BUFFER_SIZE);
+            inputStream = new GZIPInputStream(new FileInputStream(base.path), GZIP_BUFFER_SIZE);
         }
 
         @Override
@@ -99,13 +101,13 @@ public class GZIPConnections {
         }
 
         @Override
-        public void close() throws IOException {
+        public void closeAndDestroy() throws IOException {
             base.closed = true;
-            internalClose();
+            close();
         }
 
         @Override
-        public void internalClose() throws IOException {
+        public void close() throws IOException {
             inputStream.close();
         }
 
@@ -116,7 +118,7 @@ public class GZIPConnections {
 
         GZIPOutputRConnection(GZIPRConnection base) throws IOException {
             super(base);
-            outputStream = new GZIPOutputStream(new FileOutputStream(base.path), RConnection.GZIP_BUFFER_SIZE);
+            outputStream = new GZIPOutputStream(new FileOutputStream(base.path), GZIP_BUFFER_SIZE);
         }
 
         @Override
@@ -125,13 +127,13 @@ public class GZIPConnections {
         }
 
         @Override
-        public void close() throws IOException {
+        public void closeAndDestroy() throws IOException {
             base.closed = true;
-            internalClose();
+            close();
         }
 
         @Override
-        public void internalClose() throws IOException {
+        public void close() throws IOException {
             flush();
             outputStream.close();
         }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/RConnection.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/RConnection.java
index 2b26d002949b54d3641dcd6d84a1197af61c45f0..2c3f7182e41b1e7a148f34c36b1ea0aa4798a20f 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/RConnection.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/RConnection.java
@@ -32,10 +32,10 @@ import com.oracle.truffle.r.runtime.data.model.*;
 
 /**
  * Denotes an R {@code connection} instance used in the {@code base} I/O library.
+ *
+ * TODO Refactor the pushBack code into ConnectionsSupport
  */
-public abstract class RConnection implements RClassHierarchy {
-
-    public static final int GZIP_BUFFER_SIZE = (2 << 20);
+public abstract class RConnection implements RClassHierarchy, AutoCloseable {
 
     private LinkedList<String> pushBack;
 
@@ -158,7 +158,7 @@ public abstract class RConnection implements RClassHierarchy {
     /**
      * Close the connection. The corresponds to the {@code R close} function.
      */
-    public abstract void close() throws IOException;
+    public abstract void closeAndDestroy() throws IOException;
 
     /**
      * Returns {@ode true} iff we can read on this connection.
@@ -171,30 +171,33 @@ public abstract class RConnection implements RClassHierarchy {
     public abstract boolean canWrite();
 
     /**
-     * Forces the connection open. If the connection was already open, returns {@code true} and does
-     * nothing. Otherwise, tries to open the connection in the given mode, returning {@code false}
-     * if successful and throwing an {@link IOException} if not.
+     * Forces the connection open. If the connection was already open does nothing. Otherwise, tries
+     * to open the connection in the given mode. In either case returns an opened connection.
+     *
+     * builtins that need to ensure that a connection is open should use thr try-with-resources
+     * pattern, e.g:
      *
-     * For builtins that implicitly open/close a connection, the following idiom should be used:
      *
      * <pre>
      * boolean wasOpen = true;
-     * try {
-     *     wasOpen = conn.forceOpen(mode);
-     * } finally {
-     *     if (!wasOpen) {
-     *         conn.internalClose();
-     *     }
+     * try (RConnection openConn = conn.forceOpen(mode)) {
+     *     // work with openConn
+     * } catch (IOException ex) {
+     *     throw RError ...
      * }
      * </pre>
+     *
+     * N.B. While the returned value likely will be the same as {@code this}, callers should not
+     * rely on it but should use the result in the body of the {@code try} block. If the connection
+     * cannot be opened {@link IOException} is thrown.
      */
-    public abstract boolean forceOpen(String modeString) throws IOException;
+    public abstract RConnection forceOpen(String modeString) throws IOException;
 
     /**
      * Closes the internal state of the stream, but does not set the connection state to "closed",
      * i.e., allowing it to be re-opened.
      */
-    public abstract void internalClose() throws IOException;
+    public abstract void close() throws IOException;
 
     /**
      * Implements {@link RClassHierarchy}.
@@ -289,4 +292,9 @@ public abstract class RConnection implements RClassHierarchy {
      */
     public abstract boolean isTextMode();
 
+    /**
+     * Returns {@code true} iff this connection is open.
+     */
+    public abstract boolean isOpen();
+
 }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/SocketConnections.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/SocketConnections.java
index a56f6bf310b2a6a5a5bbac3e307b8463fa3cf715..aee838251c79dbf807f3dfa9141f5e4f1d2b9bbf 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/SocketConnections.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/SocketConnections.java
@@ -46,7 +46,7 @@ public class SocketConnections {
         protected final int timeout;
 
         public RSocketConnection(String modeString, boolean server, String host, int port, boolean blocking, int timeout) throws IOException {
-            super(ConnectionClass.Socket, modeString);
+            super(ConnectionClass.Socket, modeString, AbstractOpenMode.Read);
             this.server = server;
             this.host = host;
             this.port = port;
@@ -142,13 +142,13 @@ public class SocketConnections {
         }
 
         @Override
-        public void close() throws IOException {
+        public void closeAndDestroy() throws IOException {
             base.closed = true;
-            internalClose();
+            close();
         }
 
         @Override
-        public void internalClose() throws IOException {
+        public void close() throws IOException {
             socket.close();
         }
 
@@ -167,8 +167,8 @@ public class SocketConnections {
         }
 
         @Override
-        public void internalClose() throws IOException {
-            super.internalClose();
+        public void close() throws IOException {
+            super.close();
             serverSocket.close();
         }
     }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/StdConnections.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/StdConnections.java
index 3b43c51c58b0e711802a47b205a0847e0cb051bf..fc499f6425973db66f72c40797ecdb8c2d673b21 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/StdConnections.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/StdConnections.java
@@ -33,14 +33,28 @@ import com.oracle.truffle.r.runtime.conn.ConnectionSupport.*;
 import com.oracle.truffle.r.runtime.data.model.*;
 
 public class StdConnections {
+    private static StdinConnection stdin;
+    private static StdoutConnection stdout;
+    private static StdoutConnection stderr;
+
+    public static void initialize() {
+        // This ensures the connections are initialized on engine startup.
+        try {
+            stdin = new StdinConnection();
+            stdout = new StdoutConnection(false);
+            stderr = new StdoutConnection(true);
+        } catch (IOException ex) {
+            Utils.fail("failed to open stdconnections:");
+        }
+    }
+
     /**
      * Subclasses are special in that they do not use delegation as the connection is always open.
      */
     private abstract static class StdConnection extends BaseRConnection {
-        StdConnection(OpenMode openMode, int index) {
-            super(ConnectionClass.Terminal, openMode, true);
+        StdConnection(AbstractOpenMode openMode, int index) throws IOException {
+            super(openMode, index);
             this.opened = true;
-            ConnectionSupport.setStdConnection(index, this);
         }
 
         @Override
@@ -54,7 +68,7 @@ public class StdConnections {
         }
 
         @Override
-        public void close() throws IOException {
+        public void closeAndDestroy() throws IOException {
             throw new IOException(RError.Message.CANNOT_CLOSE_STANDARD_CONNECTIONS.message);
         }
 
@@ -79,15 +93,15 @@ public class StdConnections {
         }
 
         @Override
-        public boolean forceOpen(String modeString) {
-            return true;
+        public RConnection forceOpen(String modeString) {
+            throw RInternalError.shouldNotReachHere();
         }
     }
 
     private static class StdinConnection extends StdConnection {
 
-        StdinConnection() {
-            super(new OpenMode("r", AbstractOpenMode.Read), 0);
+        StdinConnection() throws IOException {
+            super(AbstractOpenMode.Read, 0);
         }
 
         @Override
@@ -129,8 +143,6 @@ public class StdConnections {
 
     }
 
-    private static final StdinConnection stdin = new StdinConnection();
-
     public static RConnection getStdin() {
         return stdin;
     }
@@ -139,8 +151,8 @@ public class StdConnections {
 
         private final boolean isErr;
 
-        StdoutConnection(boolean isErr) {
-            super(new OpenMode("w", AbstractOpenMode.Write), isErr ? 2 : 1);
+        StdoutConnection(boolean isErr) throws IOException {
+            super(AbstractOpenMode.Write, isErr ? 2 : 1);
             this.opened = true;
             this.isErr = isErr;
         }
@@ -186,14 +198,10 @@ public class StdConnections {
         }
     }
 
-    private static final StdoutConnection stdout = new StdoutConnection(false);
-
     public static RConnection getStdout() {
         return stdout;
     }
 
-    private static final StdoutConnection stderr = new StdoutConnection(true);
-
     public static RConnection getStderr() {
         return stderr;
     }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/TextConnections.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/TextConnections.java
index 0f23c4358637248dc84d447a6fd40b88c3c7f0dc..e9488708c15c1e3e0efdc545bcd5941ff37f0777 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/TextConnections.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/TextConnections.java
@@ -38,7 +38,7 @@ public class TextConnections {
         protected REnvironment env;
 
         public TextRConnection(String nm, RAbstractStringVector object, REnvironment env, String modeString) throws IOException {
-            super(ConnectionClass.Text, modeString);
+            super(ConnectionClass.Text, modeString, AbstractOpenMode.Read);
             this.nm = nm;
             this.object = object;
             this.env = env;
@@ -105,12 +105,12 @@ public class TextConnections {
         }
 
         @Override
-        public void close() throws IOException {
+        public void closeAndDestroy() throws IOException {
             base.closed = true;
         }
 
         @Override
-        public void internalClose() {
+        public void close() {
         }
 
         @Override
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/URLConnections.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/URLConnections.java
index 41bc5cfaa70e19406b789ebd1b2af3186f0aecdb..94ae7582e10f813332198d80d8fe1d5aa85ebad4 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/URLConnections.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/URLConnections.java
@@ -36,7 +36,7 @@ public class URLConnections {
         protected final String urlString;
 
         public URLRConnection(String url, String modeString) throws IOException {
-            super(ConnectionClass.URL, modeString);
+            super(ConnectionClass.URL, modeString, AbstractOpenMode.Read);
             this.urlString = url;
         }
 
@@ -90,13 +90,13 @@ public class URLConnections {
         }
 
         @Override
-        public void close() throws IOException {
+        public void closeAndDestroy() throws IOException {
             base.closed = true;
-            internalClose();
+            close();
         }
 
         @Override
-        public void internalClose() throws IOException {
+        public void close() throws IOException {
             inputStream.close();
         }