-
-
Notifications
You must be signed in to change notification settings - Fork 628
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Create infrastructure for running interactive local process #8495
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This LGTM. If the Workspace solution made sense to everyone, this is just the same pattern for another side-effecting io operation. Whatever we were / are going to do to robustify / improve / evolve Workspace surely applies here too.
} | ||
|
||
// deliberately do-nothing SIGINT handler | ||
ctrlc::set_handler(|| {}).map_err(|e| e.to_string())?; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this will need to use tokio-net's ctrl-c: Detegr/rust-ctrlc#30
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The shape looks reasonable to me, with one comment
} | ||
|
||
// deliberately do-nothing SIGINT handler | ||
ctrlc::set_handler(|| {}).map_err(|e| e.to_string())?; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We'll want to remove this signal handler (and reset it to whatever it was set to in python) when this function finishes...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, I'm not happy with this solution either, but I'm not sure what the right way is to save the existing SIGINT handler and restore it after the subprocess execution is done (although I'll check out @jsirois 's link in the above comment).
ea94ec0
to
1d5ad31
Compare
Problem
SolutionThis commit introduces a new type This commit also happens to include the stub of a v2 |
c71be9c
to
d7f50e5
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Generally looks nice - thanks!
else: | ||
state = Return(self._from_value(raw_root.handle)) | ||
roots.append(state) | ||
finally: | ||
self._native.lib.nodes_destroy(raw_roots) | ||
|
||
if remaining_runtime_exceptions_to_capture: | ||
raise ExecutionError('Internal logic error in scheduler: expected elements in ' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The error message here appears to be the negation of the if condition?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is coming from one of the commits @cosmicexplorer had in his currently-open-PR that I rebased off of becuase the bug he fixed was affecting me. I'm not sure if makes sense to try to get that merged and then merge this PR after that, or just merge this one with those commits.
Some(TempDir::new().map_err(|err| format!("Error creating tempdir: {}", err))?) | ||
}; | ||
|
||
maybe_tempdir |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Personal style thing: I find:
if let Some(tempdir) = maybe_tempdir {
command.current_dir(tempdir.path())
}
more straightforward to read than a side-effecting map of an Option
:)
src/rust/engine/src/externs.rs
Outdated
value: &Value, | ||
field: &str, | ||
) -> Result<BTreeMap<String, String>, String> { | ||
let mut map: BTreeMap<String, String> = BTreeMap::new(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This can be implemented kind of cutely as:
Ok(parts.into_iter().tuples<(_, _)>().collect())
33caec7
to
f96d141
Compare
Draft of what an interactive process runner might look like
Instead of establishing a rust signal handler, use the ExceptionSink infrastructure that already exists to selectively ignore SIGINT. In the V2 engine, a SIGINT raised when execution is in rust does not get handled by the python signal handler until sometime after the engine is finished executing a goal, which is why the existing `ignoring_sigint` context in `ExceptionSink` does not work (it successfuly increments and then decrements _threads_ignoring_sigint; but the signal is only handled *after* that happens).
Use a bool flag instead to make it easier to pass across FFI.
f96d141
to
81a7f66
Compare
### Problem The rust level `Node::cacheable` flag is currently only used to mark `@goal_rule`s as uncacheable (because they are allowed to operate on `@sideeffecting` types, such as the `Console` and the `Workspace`). But since the implementation of `cacheable` did not allow it to operate deeply in the Graph, we additionally needed to mark their parent `Select` nodes uncacheable, and could not use the flag in more positions. Via #7350, #8495, #8347, and #8974, it has become clear that we would like to safely allow nodes deeper in the graph to be uncacheable, as this allows for the re-execution of non-deterministic processes, or re-consumption of un-trackable state, such as: 1. a process receiving stdin from a user 2. an intrinsic rule that pokes an un-watched file on the filesystem 3. interacting with a stateful process like git Note that these would all be intrinsic Nodes: it's not clear that we want to expose this facility to `@rule`s directly. ### Solution Finish adding support for uncacheable nodes. Fixes #6598. When an uncacheable node completes, it will now keep the value it completed with (in order to correctly compute a `Generation` value), but it will re-compute the value once per `Session`. The accurate `Generation` value for the uncacheable node allows its dependents to "clean" themselves and not re-run unless the uncacheable node produced a different value than it had before. ### Result The `Node::cacheable` flag may be safely used deeper in the graph, with the semantics that requests for any of an uncacheable node's dependents will cause it to re-run once per `Session`. The dependents will not re-run unless the value of the uncacheable node changes (regardless of the `Session`).
Draft of what an interactive process runner might look like, along with the stub of a
run
@console_rule
. This isn't complete yet but I wanted to see what other people thought of this design.