The two sweeps do not race a printing fixture against a clock
dev-chatty.flan outlives the surveys' twenty seconds by design, and unlike dev-repl it prints while it does -- so the two backends stop at different lines and the diff reports on scheduling rather than on lowering. It joins dev-loop and dev-watch in the excluded-by-name list in both sweeps, with the distinction written down. rt_flush_out is guarded on __wasm__: the pipe it is careful about belongs to a merged flan dev, which is only ever a native host, and wasm32 need not answer for a descriptor mode its runtime may model differently. And three comments that went false with the _exit: the atexit registration in the merged entry point is no longer there for rt_die, which unlinks the socket for itself now, so both places that said so say what it is actually left covering.
This commit is contained in:
parent
95058502f5
commit
8e5fcf54cc
28
lib/dev.ml
28
lib/dev.ml
@ -3146,15 +3146,19 @@ int flan_merged_program_state(void) {
|
|||||||
* message has already sent two investigations in this repository to the wrong
|
* message has already sent two investigations in this repository to the wrong
|
||||||
* place. Gone is the honest state, and the client already has words for it.
|
* place. Gone is the honest state, and the client already has words for it.
|
||||||
*
|
*
|
||||||
* [atexit] covers exit(3), which is the compiler thread's own way out and the
|
* [atexit] covers exit(3), and what is left taking exit(3) here is narrower
|
||||||
* way out of a program that somehow returns from main. It does NOT cover the
|
* than it was: the two places a program dies where it stands — rt_die in
|
||||||
* two places a program dies where it stands: rt_die in flan_rt.c and die_now
|
* flan_rt.c and die_now in flan_agent.c — both take _exit, because the atexit
|
||||||
* in flan_agent.c both take _exit, because the atexit chain and the ELF
|
* chain and the ELF destructors want the loader lock a dlopening listener
|
||||||
* destructors want the loader lock a dlopening listener thread may be holding
|
* thread may be holding, and in this build that chain also holds OCaml's
|
||||||
* — and in this build that chain also holds OCaml's shutdown. Both of them
|
* shutdown. Both therefore unlink this path by hand, so the same four lines
|
||||||
* therefore unlink this path by hand, which is why this function's body is
|
* exist in three places rather than one — sharing them would mean a runtime
|
||||||
* written out three times in the tree rather than shared: it is four lines, and
|
* that links against the daemon, which is a worse trade than the repetition.
|
||||||
* the alternative is a runtime that has to link against the daemon. */
|
*
|
||||||
|
* What is left for this one is every exit(3) nobody planned — an OCaml fatal
|
||||||
|
* on the compiler thread most of all, since [Stdlib.exit] ends in the C one.
|
||||||
|
* Four lines on a path nobody means to take is the right price for a socket
|
||||||
|
* that never sits on disk refusing connects. */
|
||||||
static void flan_merged_unlink_sock(void) {
|
static void flan_merged_unlink_sock(void) {
|
||||||
const char *s = getenv("FLAN_DEV_SOCK");
|
const char *s = getenv("FLAN_DEV_SOCK");
|
||||||
if (s != NULL && *s != '\0') unlink(s);
|
if (s != NULL && *s != '\0') unlink(s);
|
||||||
@ -3234,9 +3238,9 @@ int main(int argc, char **argv) {
|
|||||||
* own shutdown to that chain. The hand-written [flan_merged_unlink_sock] that
|
* own shutdown to that chain. The hand-written [flan_merged_unlink_sock] that
|
||||||
* used to sit under this function's _exit went with it for the same reason —
|
* used to sit under this function's _exit went with it for the same reason —
|
||||||
* there is no way out of here any more to unlink on. The [atexit]
|
* there is no way out of here any more to unlink on. The [atexit]
|
||||||
* registration above stays, because it is not for this path: it is for
|
* registration above stays, and no longer because of the trap: rt_die takes
|
||||||
* exit(3), which is what flan_rt.c's rt_die takes, and a merged daemon that
|
* _exit now and unlinks for itself, exactly as die_now does. What is left
|
||||||
* dies through a trap must not leave a socket refusing connects behind it. */
|
* for it is written at [flan_merged_unlink_sock]. */
|
||||||
for (;;) {
|
for (;;) {
|
||||||
if (setjmp(program_return) == 0) {
|
if (setjmp(program_return) == 0) {
|
||||||
rc = flan_program_main(argc, argv);
|
rc = flan_program_main(argc, argv);
|
||||||
|
|||||||
@ -394,7 +394,9 @@ void flan_escape_bytes(const uint8_t *p, int64_t n, flan_slice *out) {
|
|||||||
* redirected stdout is not, so without this the error appears above the output
|
* redirected stdout is not, so without this the error appears above the output
|
||||||
* that led to it. */
|
* that led to it. */
|
||||||
|
|
||||||
|
#if !defined(__wasm__)
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
|
#endif
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
/* That flush, made incapable of waiting.
|
/* That flush, made incapable of waiting.
|
||||||
@ -416,12 +418,24 @@ void flan_escape_bytes(const uint8_t *p, int64_t n, flan_slice *out) {
|
|||||||
* The return value is ignored deliberately, twice over: a failed fcntl leaves
|
* The return value is ignored deliberately, twice over: a failed fcntl leaves
|
||||||
* the old blocking behaviour, which is what this code did before, and a flush
|
* the old blocking behaviour, which is what this code did before, and a flush
|
||||||
* that reports EAGAIN has done as much as it is going to. There is nothing a
|
* that reports EAGAIN has done as much as it is going to. There is nothing a
|
||||||
* dying process can do about either. */
|
* dying process can do about either.
|
||||||
|
*
|
||||||
|
* Guarded on __wasm__, which this file otherwise does only for the valgrind
|
||||||
|
* client request below. The hazard is a pipe whose reader is
|
||||||
|
* the compiler thread of a merged `flan dev', which is a native host and only
|
||||||
|
* ever a native host — a wasm32 module has no compiler beside it and no such
|
||||||
|
* pipe. So the guard is not a portability apology: it says where the problem
|
||||||
|
* can exist, and keeps wasm32 from having to answer for a descriptor mode its
|
||||||
|
* runtime may model differently. */
|
||||||
|
#if defined(__wasm__)
|
||||||
|
static void rt_flush_out(void) { (void)fflush(stdout); }
|
||||||
|
#else
|
||||||
static void rt_flush_out(void) {
|
static void rt_flush_out(void) {
|
||||||
int flags = fcntl(1, F_GETFL, 0);
|
int flags = fcntl(1, F_GETFL, 0);
|
||||||
if (flags >= 0) (void)fcntl(1, F_SETFL, flags | O_NONBLOCK);
|
if (flags >= 0) (void)fcntl(1, F_SETFL, flags | O_NONBLOCK);
|
||||||
(void)fflush(stdout);
|
(void)fflush(stdout);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/* [_exit] and not [exit], for the reason die_now gives in
|
/* [_exit] and not [exit], for the reason die_now gives in
|
||||||
* vendor/agent/flan_agent.c and gives at length: this runs on the game thread,
|
* vendor/agent/flan_agent.c and gives at length: this runs on the game thread,
|
||||||
|
|||||||
@ -59,9 +59,11 @@ fi
|
|||||||
corpus=${SURVEY_CORPUS:-$root}
|
corpus=${SURVEY_CORPUS:-$root}
|
||||||
out=$(mktemp -d); trap 'rm -rf "$out"' EXIT
|
out=$(mktemp -d); trap 'rm -rf "$out"' EXIT
|
||||||
|
|
||||||
# The two that run until something stops them, excluded by name for the reason
|
# The ones that run until something stops them, excluded by name for the reason
|
||||||
# the x86 sweep excludes them: a timeout cannot tell them from a hang.
|
# the x86 sweep excludes them: a timeout cannot tell them from a hang -- and in
|
||||||
forever="dev-loop dev-watch"
|
# dev-chatty's case cannot even give the two sides the same truncation, since
|
||||||
|
# it prints 4K a frame for as long as it is allowed to.
|
||||||
|
forever="dev-loop dev-watch dev-chatty"
|
||||||
|
|
||||||
TIMEOUT=${TIMEOUT:-20}
|
TIMEOUT=${TIMEOUT:-20}
|
||||||
|
|
||||||
|
|||||||
@ -61,10 +61,19 @@ corpus=${SURVEY_CORPUS:-$root}
|
|||||||
|
|
||||||
out=$(mktemp -d); trap 'rm -rf "$out"' EXIT
|
out=$(mktemp -d); trap 'rm -rf "$out"' EXIT
|
||||||
|
|
||||||
# The two that run until something stops them. Not a failure and not a match;
|
# The ones that run until something stops them. Not a failure and not a match;
|
||||||
# they are excluded by name because a timeout cannot tell them apart from a
|
# they are excluded by name because a timeout cannot tell them apart from a
|
||||||
# backend that hung.
|
# backend that hung.
|
||||||
forever="dev-loop dev-watch"
|
#
|
||||||
|
# dev-chatty is the third and is here for a sharper reason than the other two.
|
||||||
|
# It also outlives the timeout -- it is sized to outlast test_dev's checks and
|
||||||
|
# is killed with the connection -- but what makes it unusable here is that it
|
||||||
|
# *prints* while it does, 4K a frame. Two backends stopped by a clock stop at
|
||||||
|
# different lines, so the diff is a report about scheduling rather than about
|
||||||
|
# lowering, and it fails the alias every run. dev-repl outlives the timeout in
|
||||||
|
# the same way and is not listed, because it prints nothing and the two
|
||||||
|
# truncations are both empty.
|
||||||
|
forever="dev-loop dev-watch dev-chatty"
|
||||||
|
|
||||||
TIMEOUT=${TIMEOUT:-20}
|
TIMEOUT=${TIMEOUT:-20}
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user