@adam-fowler if you don't mind, please ping me once done. Happy to help look.
Do I understand this correctly that this is about buffering issues with print(...)? If yes, is it going to a pipe, a file or a terminal? If not, the remainder here is likely irrelevant.
Because print goes through stdio's buffering system which defaults to
- stdout: line buffered if connected to terminal
- stdout: buffered (up to a few kB) if not going to a terminal
- stderr: unbuffered
The effects can be seen here (assuming all of these are run in a terminal):
With this, the hello will show up only after 10 seconds because stdout is line buffered by default when connected to a terminal (and because of terminator: "" we don't print a newline so the buffer doesn't get flushed).
$ echo 'import Darwin; print("hello", terminator: ""); sleep(10)' | swift -
[10 seconds wait]
hello
With this however, the hello shows up immediately (because we're printing a newline):
$ echo 'import Darwin; print("hello"); sleep(10)' | swift -
hello
Lastly, this | cat will cause the hello to appear after the 10 seconds only because we're fully buffered when writing to a file.
$ echo 'import Darwin; print("hello"); sleep(10)' | swift - | cat
[10 seconds wait]
hello
Note that in most CI systems, stdout is normally connected to a pipe (for the orchestrator to capture the output), hence it might often appear to be stuck for a while.
Apart from the delays, there is one more issue: If we crash (or get killed) before the buffer gets flushed, we don't see anything. Nicely visible here:
If we're connected to a pipe, the hello is lost (because we never got to flush the buffer).
$ echo 'import Darwin; print("hello"); kill(getpid(), SIGKILL)' | swift - | cat
[the hello does not get printed]
Buf if we're connected to a terminal it prints because the buffer gets flushed on newline
$ echo 'import Darwin; print("hello"); kill(getpid(), SIGKILL)' | swift -
hello
Killed: 9
FWIW, if you want to change the buffering, you have two options:
fflush(stdout) to flush the buffer immediately
set(v)buf to change the default buffering behaviour. With that it's possible to change stdout to be line-buffered even when connected to a pipe.