liminal_server/server/connection/
supervisor.rs1#[cfg(feature = "test-support")]
2#[path = "supervisor/console_for_tests.rs"]
3pub(super) mod console_for_tests;
4#[path = "supervisor/force_close.rs"]
5mod force_close;
6#[cfg(test)]
7#[path = "process/force_close_tests.rs"]
8mod force_close_tests;
9#[path = "supervisor/retirement.rs"]
10mod retirement;
11
12use retirement::NativeRetirements;
13
14#[path = "supervisor/routed_push.rs"]
15mod routed_push;
16#[path = "supervisor/tap_placements.rs"]
17mod tap_placements;
18use std::collections::HashMap;
19#[cfg(test)]
20use std::collections::VecDeque;
21use std::collections::hash_map::Entry;
22use std::net::{SocketAddr, TcpStream};
23use std::os::fd::RawFd;
24#[cfg(test)]
25use std::sync::Barrier;
26use std::sync::atomic::{AtomicBool, AtomicU64, Ordering};
27use std::sync::mpsc::{Receiver, RecvTimeoutError, Sender, TryRecvError, channel};
28use std::sync::{Arc, Condvar, Mutex, MutexGuard, OnceLock, PoisonError, Weak};
29use std::time::{Duration, Instant};
30
31use beamr::atom::{Atom, AtomTable};
32use beamr::module::ModuleRegistry;
33use beamr::native::native_process::NativeHandlerFactory;
34use beamr::process::ExitReason;
35use beamr::scheduler::{NativeBifs, ReadinessToken, Scheduler, SchedulerConfig, SchedulerServices};
36use beamr::timer::TimerRef;
37
38use liminal::protocol::{Frame, WorkerRefusal, WorkerRegistration};
39use liminal_protocol::wire::ConnectionIncarnation;
40
41use super::incarnation::ConnectionIncarnationAuthority;
42use super::loopback::{LoopbackConnectionProcess, LoopbackServerEnd};
43use super::notifier::ConnectionNotifier;
44use super::outbound::OutboundError;
45use super::process::ConnectionProcess;
46use super::refusal::AdmissionRefusal;
47#[cfg(any(test, feature = "test-support"))]
48use super::services::LiminalConnectionServices;
49use super::services::{ConnectionServices, build_connection_services};
50#[cfg(test)]
51use super::services::{SubsystemFactory, build_connection_services_via};
52use crate::ServerError;
53use crate::auth_pass::{PassPrincipal, PassVerifier};
54use crate::config::types::{AuthConfig, LimitsConfig, ServerConfig};
55use crate::health::AdmissionReadiness;
56use crate::server::mount::MountKind;
57use crate::server::participant::{
58 CandidateLaneListener, ConnectionFateClass, InstalledParticipantService,
59 ParticipantSemanticHandler, ParticipantServiceFatal,
60};
61use crate::server::shutdown::ShutdownHandle;
62use crate::server::signals::ServerSignals;
63
64const CONNECTION_SCHEDULER_THREADS: usize = 4;
65const CONNECTION_SHUTDOWN_CONTROL_ATOM: &str = "liminal_server_connection_shutdown_control";
66const CONNECTION_READY_ATOM: &str = "liminal_server_connection_ready";
69
70#[path = "supervisor_fate.rs"]
71mod fate;
72use fate::ParkedConnectionFates;
73#[cfg(test)]
74#[path = "supervisor_fate_tests.rs"]
75mod fate_tests;
76#[path = "supervisor_lifecycle.rs"]
77mod lifecycle;
78#[path = "supervisor_reclaim.rs"]
79mod reclaim;
80#[cfg(test)]
81use reclaim::run_for_test as run_reclaim_reactor;
82#[path = "relay_pump.rs"]
83pub(super) mod relay_pump;
84#[cfg(test)]
85#[path = "../shutdown_store_tests.rs"]
86mod shutdown_store_tests;
87#[cfg(test)]
88#[path = "supervisor_shutdown_wake_tests.rs"]
89mod shutdown_wake_tests;
90#[cfg(test)]
91#[path = "supervisor_tests.rs"]
92mod tests;
93
94#[cfg(test)]
95#[path = "worker_refusal_tests.rs"]
96mod worker_refusal_tests;
97
98#[derive(Clone, Debug)]
100pub struct ConnectionSupervisor {
101 inner: Arc<SupervisorInner>,
102}
103
104use super::{service_directory, services, state, wake};
105use builder::{
106 ConnectionSupervisorBuilder, LysInstall, configured_authentication, configured_lys, install_lys,
107};
108#[cfg(test)]
109use handle::PushReplyFailure;
110use handle::{ConnectionHandle, PushReplyAwaiter};
111use inner::SupervisorInner;
112use push_types::{
113 PendingPush, PushBinding, PushReplyDisposition, PushSlotDisposition, PushSlotResolution,
114};
115use registry::{
116 ConnectionRecord, QueuedConnectionControl, ReadinessRegistration, Registry, lock, recover_lock,
117};
118use runtime::{
119 ActiveConnection, AdmissionReservation, ConnectionControl, ConnectionRuntime,
120 ConnectionRuntimeInstallation, ConnectionServiceInstallation,
121};
122#[cfg(test)]
123use runtime::{CloseEventFdProbe, PreWaitBarrier, ReclaimBarrier};
124
125#[path = "supervisor/builder.rs"]
126pub(super) mod builder;
127#[path = "supervisor/context_watch.rs"]
128pub(super) mod context_watch;
129#[path = "supervisor/handle.rs"]
130pub(super) mod handle;
131#[path = "supervisor/inner.rs"]
132mod inner;
133#[path = "supervisor/push_types.rs"]
134pub(super) mod push_types;
135#[path = "supervisor/registry.rs"]
136mod registry;
137#[path = "supervisor/runtime.rs"]
138pub(super) mod runtime;
139#[path = "supervisor/runtime_admission.rs"]
140mod runtime_admission;
141#[path = "supervisor/runtime_authority.rs"]
142mod runtime_authority;
143#[path = "supervisor/runtime_close.rs"]
144mod runtime_close;
145#[path = "supervisor/runtime_control.rs"]
146mod runtime_control;
147#[path = "supervisor/runtime_fate.rs"]
148mod runtime_fate;
149#[path = "supervisor/runtime_notifier.rs"]
150mod runtime_notifier;
151#[path = "supervisor/runtime_push_admission.rs"]
152mod runtime_push_admission;
153#[path = "supervisor/runtime_push_resolution.rs"]
154mod runtime_push_resolution;
155#[path = "supervisor/runtime_readiness.rs"]
156mod runtime_readiness;
157#[path = "supervisor/runtime_registry.rs"]
158mod runtime_registry;
159#[path = "supervisor/runtime_settlement.rs"]
160mod runtime_settlement;
161#[path = "supervisor/runtime_shutdown.rs"]
162mod runtime_shutdown;
163#[cfg(test)]
164#[path = "supervisor/runtime_test_barriers.rs"]
165mod runtime_test_barriers;
166#[cfg(test)]
167#[path = "supervisor/runtime_test_construction.rs"]
168mod runtime_test_construction;
169#[cfg(test)]
170#[path = "supervisor/runtime_test_observation.rs"]
171mod runtime_test_observation;
172#[cfg(test)]
173#[path = "supervisor/shutdown_notifier_tests.rs"]
174mod shutdown_notifier_tests;
175#[path = "supervisor/supervisor_authority.rs"]
176mod supervisor_authority;
177#[path = "supervisor/supervisor_config.rs"]
178mod supervisor_config;
179#[path = "supervisor/supervisor_connections.rs"]
180mod supervisor_connections;
181#[path = "supervisor/supervisor_push.rs"]
182mod supervisor_push;
183#[path = "supervisor/supervisor_shutdown.rs"]
184mod supervisor_shutdown;
185#[cfg(test)]
186#[path = "supervisor/supervisor_test_support.rs"]
187mod supervisor_test_support;
188
189#[test]
190fn host_fd_is_closed_before_connection_close_event_handoff()
191-> Result<(), Box<dyn std::error::Error>> {
192 use std::os::fd::AsRawFd;
193 let fixture = crate::server::self_streams::tests::R3Fixture::new()?;
194 let services: Arc<dyn ConnectionServices> = fixture.services;
195 let runtime = ConnectionRuntime::for_tests(services);
196 runtime
197 .signals
198 .set(ServerSignals::default())
199 .map_err(|_| "close-event signals already installed")?;
200 let listener = std::net::TcpListener::bind("127.0.0.1:0")?;
201 let client = TcpStream::connect(listener.local_addr()?)?;
202 let (server, address) = listener.accept()?;
203 let host_fd = server.as_raw_fd();
204 let positive_control = std::fs::File::open(format!("/dev/fd/{host_fd}"))?;
205 drop(positive_control);
206 runtime.register_record(1, Some(address), None, MountKind::Tcp, Some(server))?;
207 *runtime
208 .close_event_fd_probe
209 .lock()
210 .map_err(|error| error.to_string())? = CloseEventFdProbe::Armed;
211 let removed = runtime
212 .remove(1)
213 .ok_or("fd-owning connection was not removed")?;
214 let mut probe = runtime
215 .close_event_fd_probe
216 .lock()
217 .map_err(|error| error.to_string())?;
218 let CloseEventFdProbe::Observed(observed) =
219 std::mem::replace(&mut *probe, CloseEventFdProbe::Off)
220 else {
221 return Err("close-event handoff was not observed".into());
222 };
223 drop(probe);
224 assert!(
225 observed?,
226 "connection-close event was handed off while its host fd remained open"
227 );
228 assert!(removed.fd_guard.is_none());
229 drop(removed);
230 drop(client);
231 drop(listener);
232 Ok(())
233}