-
-
Notifications
You must be signed in to change notification settings - Fork 364
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Generalize
.runBackground
to work with all kinds of subprocesses (#…
…4085) Fixes #657 We re-use `MillBackgroundWrapper` and extend it to optionally spawn subprocess instead of calling the in-process main method. There's a bit of overhead in the JVM wrapper, but we need some kind of process wrapper to manage the mutex and termination even when the Mill process terminates, and eventually when #4007 lands we can use that to provide lighter-weight wrappers. We add a shutdown hook and copy the termination grace-period logic from OS-Lib to try and gently kill the wrapped process when necessary Integrated this into `PythonModule#runBackground` and added a unit test to verify the asynchronous launch, background existence (by checking that a file lock is taken) and termination on deletion. We can integrate this into `TypescriptModule` as well but punting that for later The subprocess APIs are a mess but leaving that to fix in 0.13.0 #3772
- Loading branch information
Showing
6 changed files
with
125 additions
and
17 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
import sys | ||
import time | ||
import fcntl | ||
|
||
def main(): | ||
with open(sys.argv[1], 'a+') as file: | ||
fcntl.lockf(file.fileno(), fcntl.LOCK_EX | fcntl.LOCK_NB) | ||
time.sleep(9999) | ||
|
||
if __name__ == "__main__": | ||
main() | ||
|
42 changes: 42 additions & 0 deletions
42
pythonlib/test/src/mill/pythonlib/RunBackgroundTests.scala
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
package mill.pythonlib | ||
|
||
import mill.testkit.{TestBaseModule, UnitTester} | ||
import utest.* | ||
import mill._ | ||
|
||
object RunBackgroundTests extends TestSuite { | ||
|
||
object HelloWorldPython extends TestBaseModule { | ||
object foo extends PythonModule { | ||
override def mainScript = T.source(millSourcePath / "src" / "foo.py") | ||
} | ||
} | ||
|
||
val resourcePath = os.Path(sys.env("MILL_TEST_RESOURCE_DIR")) / "run-background" | ||
def tests: Tests = Tests { | ||
test("runBackground") { | ||
val eval = UnitTester(HelloWorldPython, resourcePath) | ||
|
||
val lockedFile = os.temp() | ||
val Right(result) = eval.apply(HelloWorldPython.foo.runBackground(Args(lockedFile))) | ||
val maxSleep = 20000 | ||
val now1 = System.currentTimeMillis() | ||
val lock = mill.main.client.lock.Lock.file(lockedFile.toString()) | ||
|
||
def sleepIfTimeAvailable(error: String) = { | ||
Thread.sleep(100) | ||
if (System.currentTimeMillis() - now1 > maxSleep) throw new Exception(error) | ||
} | ||
|
||
Thread.sleep(1000) // Make sure that the file remains locked even after a significant sleep | ||
|
||
while (lock.probe()) sleepIfTimeAvailable("File never locked by python subprocess") | ||
|
||
os.remove.all(eval.outPath / "foo" / "runBackground.dest") | ||
|
||
while (!lock.probe()) { | ||
sleepIfTimeAvailable("File never unlocked after runBackground.dest removed") | ||
} | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters