Skip to content

v.diagserver #

-os cross compiles this file into vc/v.c for every Unix, and only $if guards reach the C preprocessor there: prctl exists on Linux alone.

fn serve #

fn serve() Request

serve turns this compilation into a diagnostics server when the environment sets V_DIAGNOSTICS_SERVER, and returns an empty request at once otherwise. The work done so far - builtin, parsed - is kept for every request: each check line read on stdin is answered by a child created by fork(), which returns from here and finishes the compilation exactly as a one-shot run of the same command line would, printing its diagnostics and exiting with its exit code. Once that child is gone the server prints v-diagnostics-server: end <code> <token> on a line of its own, where the token is whatever followed check on the request line: a source line quoted in a diagnostic cannot then pass for the end of the answer. It stops when stdin closes or a quit line arrives.

A query <token> <file>:<line>:<code><column> line asks a question of the mini-VLS protocol instead, as -line-info does: its child returns the question, and answers it in place of the diagnostics. The token comes first, as the path of the file may hold spaces. The child that answered a query stays, with the program it checked: the next query goes to it while every file it read holds the same bytes, no file was added next to one of them or removed, and each import resolves to the directory it was read from, and to a new child that checks the program otherwise.

A request carries nothing else: the command line fixes the input, and with it every setting the driver derived from the input before this point. Between requests the client changes the files on disk, and it only shows the diagnostics of its own files: see V_CHECK_SELECTED_FILES_ONLY.

struct Request #

struct Request {
pub:
	question string
mut:
	questions LineReader // the next questions from the server, and its `go`
	status_fd int = -1 // where the child tells the server what it does
	inputs    Inputs // the files the check read
	buffer    []u8   // where the child reads them again
	current   bool   // they held what the check read when the child looked
	base_kb   i64    // the child's resident memory after its first answer
	work_dir  string // the input directory, which the child enters by name
}

Request is what a child of the diagnostics server was made for: answering question, the questions of a query line, or checking the program when it is empty. A child that answered can answer the next questions too, while the files it read hold what they held (see next_question).

fn (Request) answers_again #

fn (r &Request) answers_again() bool

answers_again reports whether this child can answer more questions after its first ones: the server gave it a way to receive them.

fn (Request) keep_inputs #

fn (mut r Request) keep_inputs(digests map[string]string, imports_hold fn () bool)

keep_inputs takes the files the check read, by absolute path, with the SHA-256 of what it read in each, in hexadecimal: the child answers a next question only while they hold it, no file was added next to one of them or removed, and imports_hold finds each import resolving to the directory it was read from. It reads them again already, as one may have changed meanwhile.

fn (Request) next_question #

fn (mut r Request) next_question(code int) ?string

next_question tells the server that the answer is complete, with the exit code a one-shot run would have, and returns the next question it sends, or none once the server wants no more from this child. The memory a child allocates for its answers is never freed: after it has grown by V_DIAGNOSTICS_RETIRE_MB (1024 by default) since its first answer, it answers no more, and a new child checks the program for the next question.