@@ -94,6 +94,7 @@ pub fn run(
9494 }
9595
9696 let mut container_ip = None ;
97+ let mut pasta_pid = None ;
9798 let netns_path = if network != NetworkMode :: Host {
9899 Some ( setup_netns ( & bundle_dir) ?)
99100 } else {
@@ -109,7 +110,11 @@ pub fn run(
109110 } else if network == NetworkMode :: Pasta
110111 && let Some ( ref ns) = netns_path
111112 {
112- setup_pasta ( ns, & cli. publish ) ?;
113+ pasta_pid = Some ( setup_pasta (
114+ ns,
115+ & bundle_dir. join ( "pasta.pid" ) ,
116+ & cli. publish ,
117+ ) ?) ;
113118 }
114119
115120 // ── OCI spec + exec ────────────────────────────────────────────────
@@ -139,28 +144,19 @@ pub fn run(
139144 & network,
140145 netns_path. as_deref ( ) ,
141146 container_ip,
147+ pasta_pid,
142148 ) ?;
143149
144150 let config_json = serde_json:: to_string_pretty ( & spec) ?;
145151 fs:: write ( bundle_dir. join ( "config.json" ) , & config_json) ?;
146152
147- if cli. interactive || tty {
148- let err = Command :: new ( "crun" )
149- . arg ( "run" )
150- . arg ( "--bundle" )
151- . arg ( bundle_dir)
152- . arg ( container_id)
153- . exec ( ) ;
154- Err ( err) . context ( "Failed to exec crun" )
155- } else {
156- let image_name = cli. image . as_deref ( ) . unwrap_or ( "container" ) ;
157- run_detached (
158- & bundle_dir,
159- container_id,
160- image_name,
161- cli. pidfile . as_deref ( ) ,
162- )
163- }
153+ let err = Command :: new ( "crun" )
154+ . arg ( "run" )
155+ . arg ( "--bundle" )
156+ . arg ( bundle_dir)
157+ . arg ( container_id)
158+ . exec ( ) ;
159+ Err ( err) . context ( "Failed to exec crun" )
164160}
165161
166162/// OCI poststop hook: unmount and remove the container state directory.
@@ -178,6 +174,9 @@ pub fn cleanup() -> Result<()> {
178174 ) ;
179175 let rootfs = dir. join ( "bundle/rootfs" ) ;
180176 let _ = rustix:: mount:: unmount ( & rootfs, rustix:: mount:: UnmountFlags :: DETACH ) ;
177+ if let Some ( pid) = args. pasta_pid {
178+ unsafe { libc:: kill ( pid, libc:: SIGTERM ) } ;
179+ }
181180 let netns = dir. join ( "bundle/netns" ) ;
182181 if netns. exists ( ) {
183182 if let ( Some ( id) , Some ( ip) ) = ( & args. container_id , args. container_ip ) {
@@ -192,55 +191,6 @@ pub fn cleanup() -> Result<()> {
192191 Ok ( ( ) )
193192}
194193
195- fn journal_stream_fd ( identifier : & str ) -> Result < std:: os:: fd:: OwnedFd > {
196- use std:: io:: Write ;
197- use std:: os:: unix:: net:: UnixStream ;
198-
199- let mut stream = UnixStream :: connect ( "/run/systemd/journal/stdout" )
200- . context ( "Connecting to journal socket" ) ?;
201-
202- write ! ( stream, "{identifier}\n \n 6\n 0\n 0\n 0\n 0\n " ) ?;
203- stream. flush ( ) ?;
204-
205- Ok ( std:: os:: fd:: OwnedFd :: from ( stream) )
206- }
207-
208- fn run_detached (
209- bundle_dir : & Path ,
210- container_id : & str ,
211- image_name : & str ,
212- pidfile : Option < & Path > ,
213- ) -> Result < ( ) > {
214- let journal_fd =
215- journal_stream_fd ( & format ! ( "cfsrun:{image_name}" ) ) . context ( "Creating journal stream fd" ) ?;
216- let journal_fd2 = rustix:: io:: dup ( & journal_fd) ?;
217-
218- let pidfile_path = match pidfile {
219- Some ( pf) => pf. to_owned ( ) ,
220- None => bundle_dir. join ( "container.pid" ) ,
221- } ;
222-
223- let status = Command :: new ( "crun" )
224- . arg ( "run" )
225- . arg ( "--detach" )
226- . arg ( "--bundle" )
227- . arg ( bundle_dir)
228- . arg ( "--pid-file" )
229- . arg ( & pidfile_path)
230- . arg ( container_id)
231- . stdin ( std:: process:: Stdio :: null ( ) )
232- . stdout ( std:: process:: Stdio :: from ( std:: fs:: File :: from ( journal_fd) ) )
233- . stderr ( std:: process:: Stdio :: from ( std:: fs:: File :: from ( journal_fd2) ) )
234- . status ( )
235- . context ( "Failed to run crun" ) ?;
236- ensure ! ( status. success( ) , "crun run --detach failed: {status}" ) ;
237-
238- let pid = fs:: read_to_string ( & pidfile_path) . context ( "Reading PID file" ) ?;
239- println ! ( "{}" , pid. trim( ) ) ;
240-
241- Ok ( ( ) )
242- }
243-
244194/// Mount a composefs image via FUSE (rootless).
245195fn mount_rootfs_with_fuse (
246196 repo_path : & Path ,
@@ -421,14 +371,16 @@ fn setup_netns(bundle_dir: &Path) -> Result<PathBuf> {
421371 Ok ( netns_path)
422372}
423373
424- fn setup_pasta ( netns_path : & Path , publish : & [ PortSpec ] ) -> Result < ( ) > {
374+ fn setup_pasta ( netns_path : & Path , pid_file : & Path , publish : & [ PortSpec ] ) -> Result < i32 > {
425375 let mut pasta_cmd = Command :: new ( "pasta" ) ;
426376 pasta_cmd
427377 . arg ( "--config-net" )
428378 . arg ( "--dns-forward" )
429379 . arg ( "169.254.1.1" )
430380 . arg ( "--netns" )
431381 . arg ( netns_path)
382+ . arg ( "--pid" )
383+ . arg ( pid_file)
432384 . arg ( "--quiet" ) ;
433385
434386 if publish. is_empty ( ) {
@@ -449,7 +401,8 @@ fn setup_pasta(netns_path: &Path, publish: &[PortSpec]) -> Result<()> {
449401 String :: from_utf8_lossy( & output. stderr)
450402 ) ;
451403
452- Ok ( ( ) )
404+ let pid_str = fs:: read_to_string ( pid_file) . context ( "Reading pasta PID file" ) ?;
405+ pid_str. trim ( ) . parse :: < i32 > ( ) . context ( "Parsing pasta PID" )
453406}
454407
455408fn create_detached_tmpfs ( ) -> Result < rustix:: fd:: OwnedFd > {
@@ -597,6 +550,7 @@ fn build_runtime_spec(
597550 network : & NetworkMode ,
598551 netns_path : Option < & Path > ,
599552 container_ip : Option < std:: net:: IpAddr > ,
553+ pasta_pid : Option < i32 > ,
600554) -> Result < Spec > {
601555 use std:: collections:: HashSet ;
602556
@@ -995,6 +949,10 @@ fn build_runtime_spec(
995949 hook_args. push ( "--container-ip" . into ( ) ) ;
996950 hook_args. push ( ip. to_string ( ) ) ;
997951 }
952+ if let Some ( pid) = pasta_pid {
953+ hook_args. push ( "--pasta-pid" . into ( ) ) ;
954+ hook_args. push ( pid. to_string ( ) ) ;
955+ }
998956 let hook = HookBuilder :: default ( )
999957 . path ( self_exe)
1000958 . args ( hook_args)
0 commit comments