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, IncarnationStartInputs};
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 = "supervisor/held_admission_tests.rs"]
96mod held_admission_tests;
97#[cfg(test)]
98#[path = "worker_refusal_tests.rs"]
99mod worker_refusal_tests;
100
101#[derive(Clone, Debug)]
103pub struct ConnectionSupervisor {
104 inner: Arc<SupervisorInner>,
105}
106
107use super::{service_directory, services, state, wake};
108use builder::{
109 ConnectionSupervisorBuilder, LysInstall, configured_authentication, configured_lys, install_lys,
110};
111#[cfg(test)]
112use handle::PushReplyFailure;
113use handle::{ConnectionHandle, PushReplyAwaiter};
114use inner::SupervisorInner;
115use push_types::{
116 PendingPush, PushBinding, PushReplyDisposition, PushSlotDisposition, PushSlotResolution,
117};
118use registry::{
119 ConnectionRecord, QueuedConnectionControl, ReadinessRegistration, Registry, lock, recover_lock,
120};
121use runtime::{
122 ActiveConnection, AdmissionReservation, ConnectionControl, ConnectionRuntime,
123 ConnectionRuntimeInstallation, ConnectionServiceInstallation,
124};
125#[cfg(test)]
126use runtime::{CloseEventFdProbe, PreWaitBarrier, ReclaimBarrier};
127
128#[path = "supervisor/builder.rs"]
129pub(super) mod builder;
130#[path = "supervisor/context_watch.rs"]
131pub(super) mod context_watch;
132#[path = "supervisor/handle.rs"]
133pub(super) mod handle;
134#[path = "supervisor/held_admission.rs"]
135mod held_admission;
136#[path = "supervisor/inner.rs"]
137mod inner;
138#[path = "supervisor/push_types.rs"]
139pub(super) mod push_types;
140#[path = "supervisor/registry.rs"]
141mod registry;
142#[path = "supervisor/runtime.rs"]
143pub(super) mod runtime;
144#[path = "supervisor/runtime_admission.rs"]
145mod runtime_admission;
146#[path = "supervisor/runtime_authority.rs"]
147mod runtime_authority;
148#[path = "supervisor/runtime_close.rs"]
149mod runtime_close;
150#[path = "supervisor/runtime_control.rs"]
151mod runtime_control;
152#[path = "supervisor/runtime_fate.rs"]
153mod runtime_fate;
154#[path = "supervisor/runtime_notifier.rs"]
155mod runtime_notifier;
156#[path = "supervisor/runtime_push_admission.rs"]
157mod runtime_push_admission;
158#[path = "supervisor/runtime_push_resolution.rs"]
159mod runtime_push_resolution;
160#[path = "supervisor/runtime_readiness.rs"]
161mod runtime_readiness;
162#[path = "supervisor/runtime_registry.rs"]
163mod runtime_registry;
164#[path = "supervisor/runtime_settlement.rs"]
165mod runtime_settlement;
166#[path = "supervisor/runtime_shutdown.rs"]
167mod runtime_shutdown;
168#[cfg(test)]
169#[path = "supervisor/runtime_test_barriers.rs"]
170mod runtime_test_barriers;
171#[cfg(test)]
172#[path = "supervisor/runtime_test_construction.rs"]
173mod runtime_test_construction;
174#[cfg(test)]
175#[path = "supervisor/runtime_test_observation.rs"]
176mod runtime_test_observation;
177#[cfg(test)]
178#[path = "supervisor/shutdown_notifier_tests.rs"]
179mod shutdown_notifier_tests;
180#[path = "supervisor/supervisor_authority.rs"]
181mod supervisor_authority;
182#[path = "supervisor/supervisor_config.rs"]
183mod supervisor_config;
184#[path = "supervisor/supervisor_connections.rs"]
185mod supervisor_connections;
186#[path = "supervisor/supervisor_push.rs"]
187mod supervisor_push;
188#[path = "supervisor/supervisor_shutdown.rs"]
189mod supervisor_shutdown;
190#[cfg(test)]
191#[path = "supervisor/supervisor_test_support.rs"]
192mod supervisor_test_support;
193
194#[test]
195fn host_fd_is_closed_before_connection_close_event_handoff()
196-> Result<(), Box<dyn std::error::Error>> {
197 use std::os::fd::AsRawFd;
198 let fixture = crate::server::self_streams::tests::R3Fixture::new()?;
199 let services: Arc<dyn ConnectionServices> = fixture.services;
200 let runtime = ConnectionRuntime::for_tests(services);
201 runtime
202 .signals
203 .set(ServerSignals::default())
204 .map_err(|_| "close-event signals already installed")?;
205 let listener = std::net::TcpListener::bind("127.0.0.1:0")?;
206 let client = TcpStream::connect(listener.local_addr()?)?;
207 let (server, address) = listener.accept()?;
208 let host_fd = server.as_raw_fd();
209 std::fs::symlink_metadata(format!("/dev/fd/{host_fd}"))?;
210 runtime.register_record(1, Some(address), None, MountKind::Tcp, Some(server))?;
211 *runtime
212 .close_event_fd_probe
213 .lock()
214 .map_err(|error| error.to_string())? = CloseEventFdProbe::Armed;
215 let removed = runtime
216 .remove(1)
217 .ok_or("fd-owning connection was not removed")?;
218 let mut probe = runtime
219 .close_event_fd_probe
220 .lock()
221 .map_err(|error| error.to_string())?;
222 let CloseEventFdProbe::Observed(observed) =
223 std::mem::replace(&mut *probe, CloseEventFdProbe::Off)
224 else {
225 return Err("close-event handoff was not observed".into());
226 };
227 drop(probe);
228 assert!(
229 observed?,
230 "connection-close event was handed off while its host fd remained open"
231 );
232 assert!(removed.fd_guard.is_none());
233 drop(removed);
234 drop(client);
235 drop(listener);
236 Ok(())
237}