diff --git a/ghc/lib/std/cbits/closeFile.lc b/ghc/lib/std/cbits/closeFile.lc
index 9f4c80eb8d289b2e326f1be75d0066fa1d98e8a4..611857436cf63a871bb2c77bbab0d087b50c67c0 100644
--- a/ghc/lib/std/cbits/closeFile.lc
+++ b/ghc/lib/std/cbits/closeFile.lc
@@ -13,14 +13,33 @@ closeFile(fp)
 StgForeignObj fp;
 {
     int rc;
-
-    if (unlockFile(fileno((FILE *) fp))) {
-       /* If it has been unlocked, don't bother fclose()ing */
-       return 0;
+    int unlocked=1;
+
+    if ( unlockFile(fileno((FILE *) fp)) ) {
+      /* If the file has already been unlocked (or an entry
+         for it in the locking tables couldn't be fond), could
+         mean two things:
+
+	    - we're repeating an hClose on an already
+	      closed file (this is likely to be a bug
+	      in the implementation of hClose, as this 
+	      condition should have been caught before
+	      we ended up here.)
+	      
+	    - the file wasn't locked in the first place!
+	      (file descriptors to non regular files.)
+
+	 We proceed with attempting to close the file,
+	 but don't flag the error should fclose() return
+	 EBADF
+      */
+	unlocked=0;
+	
     }
 
     while ((rc = fclose((FILE *) fp)) != 0) {
-	if (errno != EINTR) {
+        /* See above comment */
+	if ( errno != EINTR && (!unlocked && errno != EBADF ) ) {
 	    cvtErrno();
 	    stdErrno();
 	    return rc;
diff --git a/ghc/lib/std/cbits/openFile.lc b/ghc/lib/std/cbits/openFile.lc
index fb4bdfb3987c76a2d5d5bf0be61c8389408377a5..43dd1dddad30a3d8f954b7fdbeaa08eef3a6610d 100644
--- a/ghc/lib/std/cbits/openFile.lc
+++ b/ghc/lib/std/cbits/openFile.lc
@@ -234,4 +234,86 @@ StgByteArray how;
     return (StgAddr) fp;
 }
 
+/*
+ fdopen() plus implement locking.
+*/
+StgAddr
+openFd(fd,how)
+StgInt fd;
+StgByteArray how;
+{
+    int exclusive;
+    int oflags;
+    FILE* fp;
+
+    /*
+     * Since we aren't supposed to succeed when we're opening for writing and
+     * there's another writer, we can't just do an fopen() for "w" mode.
+     */
+
+    switch (how[0]) {
+    case 'a':
+	oflags = O_WRONLY | O_NOCTTY | O_APPEND;
+	exclusive = 1;
+	break;
+    case 'w':
+	oflags = O_WRONLY | O_NOCTTY;
+	exclusive = 1;
+	break;
+    case 'r':
+#if defined(cygwin32_TARGET_OS)
+	/* With cygwin32-b19, fdopen() returns EBADF under some
+	   hard-to-reproduce situations (causing hsc's renamer
+	   to break on some ~10 modules when recompiling it.)
+	   As a temporary workaround, we open files that was requested
+	   opened as read-only instead as read-write, since fdopen()
+	   only appears to fail on RO file descriptors.
+
+	   This won't have any impact on the correctness of the Haskell IO
+	   implementation since the Handle in Haskell land will record the
+	   file as being read-only, so illegal writes will be caught.
+	   
+	   ToDo: isolate and report.
+	*/
+	oflags = how[1] == '+' ? O_RDWR | O_NOCTTY : O_RDWR | O_NOCTTY;
+#else
+	oflags = how[1] == '+' ? O_RDWR | O_NOCTTY : O_RDONLY | O_NOCTTY;
+#endif
+	exclusive = 0;
+	break;
+    default:
+	fprintf(stderr, "openFd: unknown mode `%s'\n", how);
+	EXIT(EXIT_FAILURE);
+    }
+
+
+    if (lockFile(fd, exclusive) < 0) {
+	cvtErrno();
+	switch (ghc_errno) {
+	default:
+	    stdErrno();
+	    break;
+	case GHC_EACCES:
+	case GHC_EAGAIN:
+	    ghc_errtype = ERR_RESOURCEBUSY;
+	    ghc_errstr = "file is locked";
+	    break;
+	}
+	(void) close(fd);
+	return NULL;
+    }
+
+    errno = 0;			/* Just in case fdopen() is lame */
+    while ((fp = fdopen(fd, how)) == NULL) {
+	if (errno != EINTR) {
+#if defined(cygwin32_TARGET_OS) && defined(DEBUG)
+	    fprintf(stderr, "openFd %s : %s : %d : %d\n", file, how, errno, fd);
+#endif
+	    cvtErrno();
+	    (void) close(fd);
+	    return NULL;
+	}
+    }
+    return (StgAddr) fp;
+}
 \end{code}
diff --git a/ghc/lib/std/cbits/stgio.h b/ghc/lib/std/cbits/stgio.h
index 05213ec976be46b2b94ed26e5253d62842d92519..e5f62dfd219780f95874d4bdf1693384c0ca3922 100644
--- a/ghc/lib/std/cbits/stgio.h
+++ b/ghc/lib/std/cbits/stgio.h
@@ -85,6 +85,7 @@ StgInt	inputReady  PROTO((StgForeignObj,StgInt));
 
 /* openFile.lc */
 StgAddr openFile PROTO((StgByteArray, StgByteArray));
+StgAddr openFd   PROTO((StgInt, StgByteArray));
 
 /* readFile.lc */
 StgInt	readBlock PROTO((StgAddr, StgForeignObj, StgInt));