[commit: ghc] master: Release console for ghci wrapper (3ec579d)

git at git.haskell.org git at git.haskell.org
Tue Sep 26 18:43:42 UTC 2017


Repository : ssh://git@git.haskell.org/ghc

On branch  : master
Link       : http://ghc.haskell.org/trac/ghc/changeset/3ec579d5d13dd00af58380a34daa2d57f0b9aa9e/ghc

>---------------------------------------------------------------

commit 3ec579d5d13dd00af58380a34daa2d57f0b9aa9e
Author: Tamar Christina <tamar at zhox.com>
Date:   Tue Sep 26 19:43:15 2017 +0100

    Release console for ghci wrapper
    
    Summary:
    It seems the call that caused issues with the gcc wrapper before
    was needed for the ghci wrapper in order for the child process
    to be the one handling console events.
    
    This code slightly refactors the wrappers to make sure only ghci
    calls FreeConsole and nothing else.
    
    Test Plan: ./validate , open ghci.exe press ctrl+c
    
    Reviewers: RyanGlScott, austin, hvr, bgamari
    
    Reviewed By: bgamari
    
    Subscribers: rwbarton, thomie, erikd
    
    GHC Trac Issues: #14150
    
    Differential Revision: https://phabricator.haskell.org/D4028


>---------------------------------------------------------------

3ec579d5d13dd00af58380a34daa2d57f0b9aa9e
 driver/gcc/gcc.c         |  2 +-
 driver/ghc/ghc.c         |  2 +-
 driver/ghci/ghci.c       | 13 +++++++++++--
 driver/haddock/haddock.c |  2 +-
 driver/utils/cwrapper.c  |  9 ++++++++-
 driver/utils/cwrapper.h  |  6 ++++--
 6 files changed, 26 insertions(+), 8 deletions(-)

diff --git a/driver/gcc/gcc.c b/driver/gcc/gcc.c
index b398c5e..aa63bb0 100644
--- a/driver/gcc/gcc.c
+++ b/driver/gcc/gcc.c
@@ -61,6 +61,6 @@ int main(int argc, char** argv) {
     preArgv[2] = mkString("-B%s/../lib/gcc/%s/%s"    , binDir, base, version);
     preArgv[3] = mkString("-B%s/../libexec/gcc/%s/%s", binDir, base, version);
 
-    run(exePath, 4, preArgv, argc - 1, argv + 1);
+    run(exePath, 4, preArgv, argc - 1, argv + 1, NULL);
 }
 
diff --git a/driver/ghc/ghc.c b/driver/ghc/ghc.c
index 67f8f26..416f4ba 100644
--- a/driver/ghc/ghc.c
+++ b/driver/ghc/ghc.c
@@ -10,5 +10,5 @@ int main(int argc, char** argv) {
     binDir = getExecutablePath();
     exePath = mkString("%s/ghc.exe", binDir);
 
-    run(exePath, 0, NULL, argc - 1, argv + 1);
+    run(exePath, 0, NULL, argc - 1, argv + 1, NULL);
 }
diff --git a/driver/ghci/ghci.c b/driver/ghci/ghci.c
index ebf13d8..a603655 100644
--- a/driver/ghci/ghci.c
+++ b/driver/ghci/ghci.c
@@ -11,6 +11,16 @@ BOOL fileExists(const char *path) {
     return r != INVALID_FILE_ATTRIBUTES && !(r & FILE_ATTRIBUTE_DIRECTORY);
 }
 
+/* In order for this console program to pass on full event processing to called
+   process we need to remove it from the current console. Since we want the
+   child to inherit the handles so redirection etc all work we need to detach
+   from the console after the child has been created. However we don't want to
+   detach from the console in non-interactive scenarios otherwise we'll hit
+   #13411 again. So we only detach when we're sure we need to, see #14150.  */
+void ReleaseResource(void) {
+    FreeConsole();
+}
+
 int main(int argc, char** argv) {
     char *binDir;
     char *exePath;
@@ -33,6 +43,5 @@ int main(int argc, char** argv) {
         exePath = mkString("%s/ghc-stage2.exe", binDir);
     }
 
-    run(exePath, 1, preArgv, argc - 1, argv + 1);
+    run(exePath, 1, preArgv, argc - 1, argv + 1, ReleaseResource);
 }
-
diff --git a/driver/haddock/haddock.c b/driver/haddock/haddock.c
index e43d33f..79ab873 100644
--- a/driver/haddock/haddock.c
+++ b/driver/haddock/haddock.c
@@ -10,5 +10,5 @@ int main(int argc, char** argv) {
     binDir = getExecutablePath();
     exePath = mkString("%s/haddock.exe", binDir);
 
-    run(exePath, 0, NULL, argc - 1, argv + 1);
+    run(exePath, 0, NULL, argc - 1, argv + 1, NULL);
 }
diff --git a/driver/utils/cwrapper.c b/driver/utils/cwrapper.c
index 5a30274..522c2b3 100644
--- a/driver/utils/cwrapper.c
+++ b/driver/utils/cwrapper.c
@@ -70,9 +70,12 @@ char *flattenAndQuoteArgs(char *ptr, int argc, char *argv[])
     return ptr;
 }
 
+/* This function takes a callback to be called after the creation of the child
+   process but before we block waiting for the child. Can be NULL.  */
 __attribute__((noreturn)) int run (char *exePath,
                                    int numArgs1, char **args1,
-                                   int numArgs2, char **args2)
+                                   int numArgs2, char **args2,
+                                   runCallback callback)
 {
     int i, cmdline_len;
     char *new_cmdline, *ptr;
@@ -134,6 +137,10 @@ __attribute__((noreturn)) int run (char *exePath,
     /* Synchronize input and wait for target to be ready.  */
     WaitForInputIdle(pi.hProcess, INFINITE);
 
+    /* If we have a registered callback then call it before we block.  */
+    if (callback)
+      callback();
+
     switch (WaitForSingleObject(pi.hProcess, INFINITE) ) {
     case WAIT_OBJECT_0:
     {
diff --git a/driver/utils/cwrapper.h b/driver/utils/cwrapper.h
index 324470e..3e9ccd4 100644
--- a/driver/utils/cwrapper.h
+++ b/driver/utils/cwrapper.h
@@ -1,5 +1,7 @@
 
 void die(const char *fmt, ...);
 char *mkString(const char *fmt, ...);
-__attribute__((noreturn)) int run(char *exePath, int numArgs1, char **args1, int numArgs2, char **args2);
-
+typedef void (*runCallback)(void);
+__attribute__((noreturn)) int run(char *exePath, int numArgs1, char **args1,
+                                  int numArgs2, char **args2,
+                                  runCallback callback);



More information about the ghc-commits mailing list