[GHC] #15363: Do some cleaning up of the testsuite driver

#15363: Do some cleaning up of the testsuite driver -------------------------------------+------------------------------------- Reporter: lantti | Owner: (none) Type: task | Status: new Priority: low | Milestone: 8.6.1 Component: Test Suite | Version: 8.4.3 Keywords: | Operating System: Unknown/Multiple Architecture: | Type of failure: None/Unknown Unknown/Multiple | Test Case: | Blocked By: Blocking: | Related Tickets: Differential Rev(s): | Wiki Page: -------------------------------------+------------------------------------- When trying to understand the GHC test suite I noticed some small improvements that I could do to it. This would probably work nicely as my first task on GHC: Rewrite the timeout.hs in python, it doesn't seem to do anything that would strictly need the Haskell libraries to be used and it is the only part of the test suite driver that is not written in python. Or; See if the timeout scripts could be eliminated altogether as the python subprocess module that we are using can now (since python 3.3) handle timeouts by itself and using the timeout scripts effectively doubles the number of processes we need to create for each test case. Notice that the timeout scripts do more than just generating the timeout. -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/15363 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#15363: Do some cleaning up of the testsuite driver -------------------------------------+------------------------------------- Reporter: lantti | Owner: lantti Type: task | Status: new Priority: low | Milestone: 8.6.1 Component: Test Suite | Version: 8.4.3 Resolution: | Keywords: Operating System: Unknown/Multiple | Architecture: | Unknown/Multiple Type of failure: None/Unknown | Test Case: Blocked By: | Blocking: Related Tickets: | Differential Rev(s): Wiki Page: | -------------------------------------+------------------------------------- Changes (by lantti): * owner: (none) => lantti -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/15363#comment:1 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#15363: Do some cleaning up of the testsuite driver -------------------------------------+------------------------------------- Reporter: lantti | Owner: lantti Type: task | Status: new Priority: low | Milestone: 8.6.1 Component: Test Suite | Version: 8.4.3 Resolution: | Keywords: Operating System: Unknown/Multiple | Architecture: | Unknown/Multiple Type of failure: None/Unknown | Test Case: Blocked By: | Blocking: Related Tickets: | Differential Rev(s): Wiki Page: | -------------------------------------+------------------------------------- Comment (by monoidal): There's already a Python version (timeout.py), it's apparently needed sometimes on Windows; see TIMEOUT_PROGRAM in Makefile. This specialcasing is from 2009, it's likely it can be removed but it needs checking. -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/15363#comment:2 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#15363: Do some cleaning up of the testsuite driver -------------------------------------+------------------------------------- Reporter: lantti | Owner: lantti Type: task | Status: new Priority: low | Milestone: 8.6.1 Component: Test Suite | Version: 8.4.3 Resolution: | Keywords: Operating System: Unknown/Multiple | Architecture: | Unknown/Multiple Type of failure: None/Unknown | Test Case: Blocked By: | Blocking: Related Tickets: | Differential Rev(s): Wiki Page: | -------------------------------------+------------------------------------- Comment (by lantti): If I'm reading correctly the Python version is the POSIX-only one. The Haskell version is used for all Windows runs. In order to not rely on my code reading skills I manually run timeout.py on Windows and Linux (python3 timeout3 10 "sleep 2"), results: Windows says "module 'os' has no attribute 'fork'", Linux just works. The Windows version definitely still relies on the Haskell implementation. -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/15363#comment:3 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#15363: Do some cleaning up of the testsuite driver -------------------------------------+------------------------------------- Reporter: lantti | Owner: lantti Type: task | Status: new Priority: low | Milestone: 8.6.1 Component: Test Suite | Version: 8.4.3 Resolution: | Keywords: Operating System: Unknown/Multiple | Architecture: | Unknown/Multiple Type of failure: None/Unknown | Test Case: Blocked By: | Blocking: Related Tickets: | Differential Rev(s): Wiki Page: | -------------------------------------+------------------------------------- Description changed by lantti: Old description:
When trying to understand the GHC test suite I noticed some small improvements that I could do to it. This would probably work nicely as my first task on GHC:
Rewrite the timeout.hs in python, it doesn't seem to do anything that would strictly need the Haskell libraries to be used and it is the only part of the test suite driver that is not written in python.
Or;
See if the timeout scripts could be eliminated altogether as the python subprocess module that we are using can now (since python 3.3) handle timeouts by itself and using the timeout scripts effectively doubles the number of processes we need to create for each test case. Notice that the timeout scripts do more than just generating the timeout.
New description: When trying to understand the GHC test suite I noticed some small improvements that I could do to it. This would probably work nicely as my first task on GHC: Rewrite the timeout.hs in python, it is used for Windows runs but it doesn't seem to do anything that would strictly need the Haskell libraries to be used and it is the only part of the test suite driver that is not written in python. Or; See if the timeout scripts could be eliminated altogether as the python subprocess module that we are using can now (since python 3.3) handle timeouts by itself and using the timeout scripts effectively doubles the number of processes we need to create for each test case. Notice that the timeout scripts do more than just generating the timeout. -- -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/15363#comment:4 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#15363: Do some cleaning up of the testsuite driver -------------------------------------+------------------------------------- Reporter: lantti | Owner: lantti Type: task | Status: new Priority: low | Milestone: 8.6.1 Component: Test Suite | Version: 8.4.3 Resolution: | Keywords: Operating System: Unknown/Multiple | Architecture: | Unknown/Multiple Type of failure: None/Unknown | Test Case: Blocked By: | Blocking: Related Tickets: | Differential Rev(s): Wiki Page: | -------------------------------------+------------------------------------- Comment (by lantti): It seems that timeout.hs is even not fully functional under minTTY/msys2 shell at the moment. Something along the way intercepts Ctrl-c and kills the whole process tree without giving the timeout program or the testsuite cleanup code (stopNow(), etc) a chance to react to it. The bright side to this is that those cleanup routines were mostly concerned with eliminating stray processes which the shell (or whatever intercepts the Ctrl-C) seems to do for us anyway. -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/15363#comment:5 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#15363: Do some cleaning up of the testsuite driver -------------------------------------+------------------------------------- Reporter: lantti | Owner: lantti Type: task | Status: new Priority: low | Milestone: 8.6.1 Component: Test Suite | Version: 8.4.3 Resolution: | Keywords: Operating System: Unknown/Multiple | Architecture: | Unknown/Multiple Type of failure: None/Unknown | Test Case: Blocked By: | Blocking: Related Tickets: | Differential Rev(s): Wiki Page: | -------------------------------------+------------------------------------- Comment (by lantti): Using winpty instead of mintty on Windows allows the ctrl-c event to propagate through the process tree, but even then the clean up routines are not run and the results from the tests already completed are not displayed. At the moment I presume this is because the timeout.hs is not able to react to the ctrl-c event while waiting on the child process. When run in isolation it only reacts after the child returns (or never if the child ignores ctrl-c). As part of the testsuite it doesn't get a chance to react before being killed. -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/15363#comment:6 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#15363: Do some cleaning up of the testsuite driver -------------------------------------+------------------------------------- Reporter: lantti | Owner: lantti Type: task | Status: new Priority: low | Milestone: 8.6.1 Component: Test Suite | Version: 8.4.3 Resolution: | Keywords: Operating System: Unknown/Multiple | Architecture: | Unknown/Multiple Type of failure: None/Unknown | Test Case: Blocked By: | Blocking: Related Tickets: | Differential Rev(s): Wiki Page: | -------------------------------------+------------------------------------- Comment (by lantti): Eliminating timeout.py turned out to be straight forward and the current features of the subprocess module cover almost exactly what timeout.py did before, with the minor difference that the tests would be separated from the driver with a call to setsid() (creating a new session) instead of merely setpgrp() (creating a new process group). Some little speed-up was observed as each test case now needs to start one process and one python interpreter less. -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/15363#comment:7 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#15363: Do some cleaning up of the testsuite driver -------------------------------------+------------------------------------- Reporter: lantti | Owner: lantti Type: task | Status: new Priority: low | Milestone: 8.6.1 Component: Test Suite | Version: 8.4.3 Resolution: | Keywords: Operating System: Unknown/Multiple | Architecture: | Unknown/Multiple Type of failure: None/Unknown | Test Case: Blocked By: | Blocking: Related Tickets: | Differential Rev(s): Wiki Page: | -------------------------------------+------------------------------------- Comment (by bgamari): Great news. Do you have a patch to share? -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/15363#comment:8 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#15363: Do some cleaning up of the testsuite driver -------------------------------------+------------------------------------- Reporter: lantti | Owner: lantti Type: task | Status: new Priority: low | Milestone: 8.6.1 Component: Test Suite | Version: 8.4.3 Resolution: | Keywords: Operating System: Unknown/Multiple | Architecture: | Unknown/Multiple Type of failure: None/Unknown | Test Case: Blocked By: | Blocking: Related Tickets: | Differential Rev(s): Wiki Page: | -------------------------------------+------------------------------------- Comment (by lantti): Not yet, as the timeout.hs needs to be replaced as well to make this work on Windows. I could of course copy-paste the old code back in for Windows and share an intermediate patch, but I don't think we are in such a hurry with this particular ticket. -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/15363#comment:9 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#15363: Do some cleaning up of the testsuite driver -------------------------------------+------------------------------------- Reporter: lantti | Owner: lantti Type: task | Status: new Priority: low | Milestone: 8.6.1 Component: Test Suite | Version: 8.4.3 Resolution: | Keywords: Operating System: Unknown/Multiple | Architecture: | Unknown/Multiple Type of failure: None/Unknown | Test Case: Blocked By: | Blocking: Related Tickets: | Differential Rev(s): Wiki Page: | -------------------------------------+------------------------------------- Comment (by Phyx-): timeout.hs goes through great lengths to be able to reliably detect when all child processes exit using job groups. replacing this with the standard python process api will re-introduce threading issues we spent a great deal of time debugging so be careful with that. It also deals with quite a few corner cases with regards to how msys implements pipes. You would essentially have to rewrite it using ctypes because python's `os` package only provides process grouping for posix OSes. Before such a patch is accepted I'd like to see some evidence that it works correctly when the system is under heavy load. -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/15363#comment:10 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#15363: Do some cleaning up of the testsuite driver -------------------------------------+------------------------------------- Reporter: lantti | Owner: lantti Type: task | Status: new Priority: low | Milestone: 8.6.1 Component: Test Suite | Version: 8.4.3 Resolution: | Keywords: Operating System: Unknown/Multiple | Architecture: | Unknown/Multiple Type of failure: None/Unknown | Test Case: Blocked By: | Blocking: Related Tickets: | Differential Rev(s): Wiki Page: | -------------------------------------+------------------------------------- Comment (by lantti): As I mentioned earlier, Windows seems tricky. I had already come to the conclusion that python subprocess module is not going to be able to cleanly cut this, but, like you said, the next option would be a rewrite accessing winapi over ctypes and I don't see that as prohibitive in any way. I think I have reasonably good understanding of what timeout.hs is doing, but like I mentioned earlier, it doesn't seem to be fully functional in the current msys environment. I will slowly keep on investigating this when I find free moments. After I come with a patch we can discuss how to best test it. -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/15363#comment:11 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#15363: Do some cleaning up of the testsuite driver -------------------------------------+------------------------------------- Reporter: lantti | Owner: lantti Type: task | Status: patch Priority: low | Milestone: 8.8.1 Component: Test Suite | Version: 8.4.3 Resolution: | Keywords: Operating System: Unknown/Multiple | Architecture: | Unknown/Multiple Type of failure: None/Unknown | Test Case: Blocked By: | Blocking: Related Tickets: | Differential Rev(s): Wiki Page: | -------------------------------------+------------------------------------- Changes (by lantti): * status: new => patch Comment: I was playing around some more with the Windows process groups but eventually went the Job Objects way. The Windows console process groups are supported by subprocess module and os module, resulting in an almost total elimination of the diverging code path and working to my satisfaction on a light load, but unfortunately not working under mintty without additional winpty wrapping and still breaking apart on heavier loads due to Windows Console signals not being guaranteed to be delivered in such cases. The Job Objects on the other hand require a long diverging code path, but were absolutely robust against my limited stress tests. A preliminary patch is submitted to Phabricator: https://phabricator.haskell.org/D5107 Some simple tests that I used to evaluate that: https://github.com/lantti/ghc/tree/testsuite-tests/testsuite/tests/aaa The patch follows the approach from timeout.hs for Windows and uses subprocess module for Posix. As the Windows code path doesn't use subprocess anymore the IO redirection and environment string generation are handled by this patch too. All in all the diverging code paths didn't get shorter, unlike I had hoped. According to my few test runs the testsuite runs slightly faster on Posix now, on Windows I don't have any coherent results of it running faster or slower. Also interrupting the test run on Windows is as sketchy as it used to be, it only works because mintty kills our process tree for us. No signals get delivered to our testsuite driver and none of our cleanup or results collecting code runs. Some related observations I made while working on this: - in addition to the signals/console incompatibility between mintty-mingw and native Windows programs, current versions of mintty-mingw have problems handling unicode environment variables, the variables get mangled already before they are passed to the python interpreter. - our Posix code (before and after the patch) leave child process management to the test process in cases of normal termination and keyboard interrupt, meaning that if the test program itself does not signal and wait for its children to terminate then nobody will. The only case where the testsuite driver takes action and signals the process group is after a timeout. -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/15363#comment:13 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#15363: Do some cleaning up of the testsuite driver -------------------------------------+------------------------------------- Reporter: lantti | Owner: lantti Type: task | Status: patch Priority: low | Milestone: 8.8.1 Component: Test Suite | Version: 8.4.3 Resolution: | Keywords: Operating System: Unknown/Multiple | Architecture: | Unknown/Multiple Type of failure: None/Unknown | Test Case: Blocked By: | Blocking: Related Tickets: | Differential Rev(s): Wiki Page: | -------------------------------------+------------------------------------- Comment (by lantti): Sorry, never mind. The patch is still unusable. My IO redirection seems to occasionally lock up on Windows. For example test "conc070" seems to be unable to run properly under the new code and eventually timeouts. Somehow I missed this earlier. -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/15363#comment:14 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#15363: Do some cleaning up of the testsuite driver -------------------------------------+------------------------------------- Reporter: lantti | Owner: lantti Type: task | Status: patch Priority: low | Milestone: 8.8.1 Component: Test Suite | Version: 8.4.3 Resolution: | Keywords: Operating System: Unknown/Multiple | Architecture: | Unknown/Multiple Type of failure: None/Unknown | Test Case: Blocked By: | Blocking: Related Tickets: | Differential Rev(s): Phab:D5107 Wiki Page: | -------------------------------------+------------------------------------- Changes (by simonpj): * differential: => Phab:D5107 -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/15363#comment:15 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#15363: Do some cleaning up of the testsuite driver -------------------------------------+------------------------------------- Reporter: lantti | Owner: lantti Type: task | Status: patch Priority: low | Milestone: 8.8.1 Component: Test Suite | Version: 8.4.3 Resolution: | Keywords: Operating System: Unknown/Multiple | Architecture: | Unknown/Multiple Type of failure: None/Unknown | Test Case: Blocked By: | Blocking: Related Tickets: | Differential Rev(s): Phab:D5107 Wiki Page: | -------------------------------------+------------------------------------- Comment (by tdammers): First of all, thanks a lot for the effort, it is very much appreciated. Then, to summarize (correct me if I'm wrong): - The original problem to be solved here is that the testsuite driver (written in Python) shells out to a custom timeout program ({{{timeout.hs}}}); so the idea was to rewrite the whole timeout functionality in Python - Vanilla Python and its libraries (particularly {{{subprocess}}}) are inadequate on Windows, because the process model is different, which makes certain things that we rely on nontrivial (specifically, reliably killing entire process trees). This is why {{{timeout.hs}}} exists in the first place, and why the proposed patch introduces {{{winbindings.py}}}. - The patch does not improve testsuite performance; the goal is to improve maintainability. This raises to the following issues: 1. Between {{{winbindings.py}}} and {{{timeout.hs}}}, I don't see a significant reduction in overall complexity. We remove Windows-specific Haskell code, and replace it with Windows-specific Python code; both are a maintenance liability. 2. {{{timeout.hs}}} works; {{{winbindings.py}}} and the rewritten test driver parts are mostly untested as of yet. There is a nonzero change of this patch introducing new, possibly subtle, bugs. 3. GHC developers are more likely to want to work on complicated Haskell code than complicated Python code, and be competent at it. So Python code in this context has a higher barrier to participation, and a smaller contributor pool to draw from. 4. Managing Python versions, especially on Windows, is a nontrivial effort. The less we rely on it, the better. 5. Given 3. and 4., and also for other reasons, we would prefer moving (parts of) the test driver from Python to Haskell, not the other way around. Ideally, we would want to see the test driver rewritten in Haskell entirely. -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/15363#comment:16 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#15363: Do some cleaning up of the testsuite driver -------------------------------------+------------------------------------- Reporter: lantti | Owner: lantti Type: task | Status: patch Priority: low | Milestone: 8.8.1 Component: Test Suite | Version: 8.4.3 Resolution: | Keywords: Operating System: Unknown/Multiple | Architecture: | Unknown/Multiple Type of failure: None/Unknown | Test Case: Blocked By: | Blocking: Related Tickets: | Differential Rev(s): Phab:D5107 Wiki Page: | -------------------------------------+------------------------------------- Comment (by lantti): I agree with this summary. To add some more (possibly superfluous) details, the original problem is not only Windows specific. In order to maintain a consistent interface the current POSIX code path also shells out an external process (a separate python interpreter) to handle the timeout and interrupting functionality even when {{{subprocess}}} functionality would be adequate on POSIX. To issue 1.: I have nothing to add. To issue 2.: I'd like to add that even {{{timeout.hs}}} itself is not fully functional at the moment, failing to handle interrupts signals, although {{{winbindings.py}}} doesn't do any better job either. Interrupting the test run on Windows works only because {{{mintty}}} simply kills our whole process tree without consulting our code at all, resulting in different but still effective end to the test run (compared to POSIX). The results for the tests already run won't get displayed in that case but fortunately this functionality doesn't strike me as essential. To issues 3,4,5: If this is the direction we should be going I'll happily align my efforts with it instead. I was under the impression that currently hs->py was the preferred way as according to the git logs (e5063a042c9a1701ea7273da7bacb530d5c077d3) GHC used to have a testsuite language and appropriate interpreter implemented all in Haskell. The stated motivation to move away from the Haskell code was maintainability but presumably we have a lot better Haskell libraries now than back then and the maintainability would perhaps not become such an issue anymore. -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/15363#comment:17 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#15363: Do some cleaning up of the testsuite driver -------------------------------------+------------------------------------- Reporter: lantti | Owner: lantti Type: task | Status: closed Priority: low | Milestone: 8.8.1 Component: Test Suite | Version: 8.4.3 Resolution: wontfix | Keywords: Operating System: Unknown/Multiple | Architecture: | Unknown/Multiple Type of failure: None/Unknown | Test Case: Blocked By: | Blocking: Related Tickets: | Differential Rev(s): Phab:D5107 Wiki Page: | -------------------------------------+------------------------------------- Changes (by lantti): * status: patch => closed * resolution: => wontfix Comment: Considering that the current scripts are not seriously broken and that the whole testsuite is evaluated for a eventual rewrite, I close this as wontfix -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/15363#comment:18 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#15363: Do some cleaning up of the testsuite driver -------------------------------------+------------------------------------- Reporter: lantti | Owner: lantti Type: task | Status: closed Priority: low | Milestone: 8.8.1 Component: Test Suite | Version: 8.4.3 Resolution: wontfix | Keywords: Operating System: Unknown/Multiple | Architecture: | Unknown/Multiple Type of failure: None/Unknown | Test Case: Blocked By: | Blocking: Related Tickets: | Differential Rev(s): Phab:D5107 Wiki Page: | -------------------------------------+------------------------------------- Comment (by Phyx-):
To issue 2.: I'd like to add that even timeout.hs itself is not fully functional at the moment, failing to handle interrupts signals, although winbindings.py doesn't do any better job either. Interrupting the test run on Windows works only because mintty simply kills our whole process tree without consulting our code at all, resulting in different but still effective end to the test run (compared to POSIX). The results for the tests already run won't get displayed in that case but fortunately this functionality doesn't strike me as essential.
This isn't a testsuite problem. It's simply because mintty suppresses all windows signals in order to implement the pseudo posix signal handlers. Mintty is simply incompatible with windows programs. That's why interfaces like winpty exist but that are ultimately a hack. The simplest solution here is simply not to use mintty. Any other terminal emulator and call bash directly. -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/15363#comment:19 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler
participants (1)
-
GHC