I’m running raco static-web from inside another Racket program using subprocess[1], and, inside a thread, monitoring the subprocess’s stdout with sync/enable-break. The weird thing is that with raco static-web in particular, the output sent by that command to stdout is not picked up by my program until the raco process is killed in some way.
Example Gist. See the screenshot at the bottom also. (I’m working on this for a GUI app, but I created this not-exactly-MVE to remove GUI stuff from the equation.) This is running on macOS.
Twist: with any other long-running program I run this way (make, raco pollen start, etc.), stuff appears on the port as it is generated by the subprocess, as expected. So it must be something to do with the way raco static-web does logging, or more specifically with the dispatcher created by make in web-server/dispatchers/dispatch-logresp.
I know that it would probably be better for me just to run the web server directly inside my own program, and that’s probably the direction I’ll go eventually. But I am very curious to understand what causes this behavior anyway. ↩︎
Can you install raco static-web from source, and revert back to df097e1475f1f6cb648f2d457e94a3dd2659542e, which is the commit right before I changed raco static-web to use dispatch-logresp? Do you get the same behavior?
In fact I have that package installed via --link from a local git clone. And yes, I do get the same behavior after checking out df097e14, deleting the compiled folder, doing raco pkg setup raco-static-web and restarting DrRacket.
So I think the difference is that Pollen uses stderr for those messages, and stderr is not buffered. On the other hand, raco static-web uses stdout, which got buffered.
…but this doesn’t keep it from behaving like a block-buffered port. I guess maybe that part is up to the OS.
Maybe the logger could be modified to flush-output more frequently? But now that the mystery is cleared up somewhat, I can move on to moving the web server inside my code rather than doing a subprocess.
Yes, this is what I had in mind as part of inlining the web server code. (I assume it’s not possible to listen to a logger from another program running under a whole other instance of racket in a subprocess…right?)
You would need some kind of inter-process communication, and there isn't any infrastructure that I know of for doing that automatically yet. Logging can automatically go to syslog, and you could read from that, or you could build your own IPC.
Here, you have full control of the application: you can parameterizecurrent-output-port, current-command-line-arguments, and whatnot. And you can run it in a separate thread.
I’ve been trying to make a GUI app that would run arbitrary command-line programs (or scripts) and display the output in an editor canvas in real time, just as if you were running it in the console. So it’s not that I specifically wanted to run a Racket program via a subprocess, I just wanted to be able to run anything and see the output in real time. My approach works great with all the commands/scripts I tested except for raco static-web. And I was too curious about why that would possibly be to drop the issue.
Assuming the problem is caused by block-buffering stdout outside of Racket’s control, there are probably many other programs/scripts that would exhibit the same problem when run from my app. And maybe there isn’t a reliable way to make this app without delving into pseudo-tty stuff, which, “that way lies madness”, likely.
But I have seen issues where in Github Actions the output is incorrectly buffered. I can't remember if that was using logging infrastructure or print/displayln.
Yep! Though, in that case, raco is being run from inside an interactive shell with a TTY device, which IIUC is not the case when running it via subprocess.