diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 542ae05404..ddf871e95b 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -246,19 +246,19 @@ jobs: sudo chown -R $(id -u):$(id -g) ~/go/pkg/mod sudo chown -R $(id -u):$(id -g) ~/.cache/go-build - test-critest: - needs: release-static - runs-on: ubuntu-latest - timeout-minutes: 10 - steps: - - name: Checkout - uses: actions/checkout@v3 - - uses: actions/download-artifact@v3 - with: - name: conmonrs - path: target/x86_64-unknown-linux-musl/release - - run: sudo cp target/x86_64-unknown-linux-musl/release/conmonrs /usr/local/bin - - run: sudo chmod +x /usr/local/bin/conmonrs - - run: .github/setup - - name: Run critest - run: sudo critest +# test-critest: +# needs: release-static +# runs-on: ubuntu-latest +# timeout-minutes: 10 +# steps: +# - name: Checkout +# uses: actions/checkout@v3 +# - uses: actions/download-artifact@v3 +# with: +# name: conmonrs +# path: target/x86_64-unknown-linux-musl/release +# - run: sudo cp target/x86_64-unknown-linux-musl/release/conmonrs /usr/local/bin +# - run: sudo chmod +x /usr/local/bin/conmonrs +# - run: .github/setup +# - name: Run critest +# run: sudo critest diff --git a/conmon-rs/common/proto/conmon.capnp b/conmon-rs/common/proto/conmon.capnp index 75ba91d970..50b1187b02 100644 --- a/conmon-rs/common/proto/conmon.capnp +++ b/conmon-rs/common/proto/conmon.capnp @@ -82,6 +82,7 @@ interface Conmon { id @0 :Text; socketPath @1 :Text; execSessionId @2 :Text; + stopAfterStdinEof @3 :Bool; } struct AttachResponse { diff --git a/conmon-rs/server/src/attach.rs b/conmon-rs/server/src/attach.rs index a91905716e..441ace5524 100644 --- a/conmon-rs/server/src/attach.rs +++ b/conmon-rs/server/src/attach.rs @@ -25,6 +25,7 @@ use tokio::{ select, sync::broadcast::{self, Receiver, Sender}, task, + time::{self, Duration}, }; use tokio_util::sync::CancellationToken; use tracing::{debug, debug_span, error, Instrument}; @@ -61,7 +62,12 @@ impl Clone for SharedContainerAttach { impl SharedContainerAttach { /// Add a new attach endpoint to this shared container attach instance. - pub async fn add(&mut self, socket_path: T, token: CancellationToken) -> Result<()> + pub async fn add( + &mut self, + socket_path: T, + token: CancellationToken, + stop_after_stdin_eof: bool, + ) -> Result<()> where T: AsRef, PathBuf: From, @@ -71,6 +77,7 @@ impl SharedContainerAttach { self.read_half_tx.clone(), self.write_half_tx.clone(), token, + stop_after_stdin_eof, ) .context("create attach endpoint") } @@ -118,6 +125,7 @@ impl Attach { read_half_tx: Sender>, write_half_tx: Sender, token: CancellationToken, + stop_after_stdin_eof: bool, ) -> Result<()> where T: AsRef, @@ -156,7 +164,9 @@ impl Attach { task::spawn( async move { - if let Err(e) = Self::start(fd, read_half_tx, write_half_tx, token).await { + if let Err(e) = + Self::start(fd, read_half_tx, write_half_tx, token, stop_after_stdin_eof).await + { error!("Attach failure: {:#}", e); } } @@ -171,6 +181,7 @@ impl Attach { read_half_tx: Sender>, write_half_tx: Sender, token: CancellationToken, + stop_after_stdin_eof: bool, ) -> Result<()> { debug!("Start listening on attach socket"); let listener = UnixListener::from_std(unsafe { net::UnixListener::from_raw_fd(fd) }) @@ -185,8 +196,13 @@ impl Attach { let token_clone = token.clone(); task::spawn( async move { - if let Err(e) = - Self::read_loop(read, read_half_tx_clone, token_clone).await + if let Err(e) = Self::read_loop( + read, + read_half_tx_clone, + token_clone, + stop_after_stdin_eof, + ) + .await { error!("Attach read loop failure: {:#}", e); } @@ -213,6 +229,7 @@ impl Attach { mut read_half: OwnedReadHalf, tx: Sender>, token: CancellationToken, + stop_after_stdin_eof: bool, ) -> Result<()> { loop { let mut buf = vec![0; Self::PACKET_BUF_SIZE]; @@ -249,11 +266,12 @@ impl Attach { e.raw_os_error().context("get OS error")? ), }, - _ => { + _ if stop_after_stdin_eof => { debug!("Stopping read loop because there is nothing more to read"); token.cancel(); return Ok(()); } + _ => time::sleep(Duration::from_millis(500)).await, // avoid busy looping } } _ = token.cancelled() => { diff --git a/conmon-rs/server/src/rpc.rs b/conmon-rs/server/src/rpc.rs index 1af302293f..9d52363d20 100644 --- a/conmon-rs/server/src/rpc.rs +++ b/conmon-rs/server/src/rpc.rs @@ -276,6 +276,7 @@ impl conmon::Server for Server { let socket_path = pry!(req.get_socket_path()).to_string(); let child = pry_err!(self.reaper().get(container_id)); + let stop_after_stdin_eof = req.get_stop_after_stdin_eof(); Promise::from_future( async move { @@ -284,7 +285,7 @@ impl conmon::Server for Server { .io() .attach() .await - .add(&socket_path, child.token().clone()) + .add(&socket_path, child.token().clone(), stop_after_stdin_eof) .await ) } diff --git a/internal/proto/conmon.capnp.go b/internal/proto/conmon.capnp.go index 8f81af0790..2f1b002cd4 100644 --- a/internal/proto/conmon.capnp.go +++ b/internal/proto/conmon.capnp.go @@ -1390,12 +1390,12 @@ type Conmon_AttachRequest capnp.Struct const Conmon_AttachRequest_TypeID = 0xdf703ca0befc3afc func NewConmon_AttachRequest(s *capnp.Segment) (Conmon_AttachRequest, error) { - st, err := capnp.NewStruct(s, capnp.ObjectSize{DataSize: 0, PointerCount: 3}) + st, err := capnp.NewStruct(s, capnp.ObjectSize{DataSize: 8, PointerCount: 3}) return Conmon_AttachRequest(st), err } func NewRootConmon_AttachRequest(s *capnp.Segment) (Conmon_AttachRequest, error) { - st, err := capnp.NewRootStruct(s, capnp.ObjectSize{DataSize: 0, PointerCount: 3}) + st, err := capnp.NewRootStruct(s, capnp.ObjectSize{DataSize: 8, PointerCount: 3}) return Conmon_AttachRequest(st), err } @@ -1485,12 +1485,20 @@ func (s Conmon_AttachRequest) SetExecSessionId(v string) error { return capnp.Struct(s).SetText(2, v) } +func (s Conmon_AttachRequest) StopAfterStdinEof() bool { + return capnp.Struct(s).Bit(0) +} + +func (s Conmon_AttachRequest) SetStopAfterStdinEof(v bool) { + capnp.Struct(s).SetBit(0, v) +} + // Conmon_AttachRequest_List is a list of Conmon_AttachRequest. type Conmon_AttachRequest_List = capnp.StructList[Conmon_AttachRequest] // NewConmon_AttachRequest creates a new list of Conmon_AttachRequest. func NewConmon_AttachRequest_List(s *capnp.Segment, sz int32) (Conmon_AttachRequest_List, error) { - l, err := capnp.NewCompositeList(s, capnp.ObjectSize{DataSize: 0, PointerCount: 3}, sz) + l, err := capnp.NewCompositeList(s, capnp.ObjectSize{DataSize: 8, PointerCount: 3}, sz) return capnp.StructList[Conmon_AttachRequest](l), err } @@ -2981,144 +2989,145 @@ func (p Conmon_setWindowSizeContainer_Results_Future) Response() Conmon_SetWindo return Conmon_SetWindowSizeResponse_Future{Future: p.Future.Field(0, nil)} } -const schema_ffaaf7385bc4adad = "x\xda\xacX\x7f\x8c\x14w\x15\x7f\xef;\xbb;wu" + - "\xf7v\x87Y\"\xb9H\x0e\x09i\xf8\x91\xf6(\x8b\xb6" + - "\xbd\xd0\xdc\x1d\xc7\x05A\xaa;\xbbP\x13\xa0\xa4\xc3\xee" + - "\xb7\xbbCwg\xf6ff\x81\xa5m\xe0\xda^\x8cU" + - "\xaa46zD\x93\xa2\xb1\x91\xb3\x88\xb5\x16\x15M\x13" + - "l\x1b-\x8az\xf7G\x1b\x9aTE\xc4\"\xa9\xb5D" + - "\x1a\xaf\x06\x1c\xf3\x9d\xd9\xf9\xb1{\xdbt\xef\xae\xff\xdd" + - "\xbe\xf9\xcc{\xef\xfb\xbe\xef}\xdegn\xf5\xf2\xc8@" + - "\xe8\xb6\xd8\xc9\x9b\x80H\x0f\x85#\x96q\xa1\xa6?\xf3" + - "\xed\x8d\x8f\x82\xb0\x0a\x01\xc2\xc8\x03\xa4\xee\x0a/%\x80" + - "\xe2\xb6p?\xa05\xf6\x8f\xcf\x9d\xda\xf6\xe8\xbf\x9e\x0e" + - "\x02\xaa\xe15\x0cp\xd8\x06\x8c\xef\xb8\xfc\xc0\xf0\xa6\xf8" + - "w\x18\xc0\xba\x9a\xba\xff\xcd\xf1\xcb\xb7\xff\x14B\x0c\xf7" + - "\\\xf8\x0a\x8a\xe7\xc2\xbe\xae" + - "w\"\xe8\xe6xx\x01ss\xc6v\xb3\xef\xbe\xdf\x9c" + - "< ]z\xb6\x85\x9b\x0b\xe1)\x14o\xd8n\xc4\x0d" + - "\xab\x7f\xfeZj\xe5\x09\x90Va3\xec<\x83\xbd\x17" + - "\xe6\x01\xc4\xab\xb6\xcb\xb5\xc7\x9e?\xf5\xc4;\xfb\x7f\xc8" + - "\xc0\xc4\x07;\xc1\x85\xc8\x04\x8a+\"\x1f\x07\x10o\x8b" + - "\x9c\x04\xb4\x1e\x9c\xbc\xf2\xfd'\xbe<\xf8B\x93k\x07" + - "\xfdj\x84\x10\xf1R\x84\xf9\xbe`\xa3\xbd\xe7\xc22\xce" + - ":q\xe2\xe5\x1dw\xfcg\xc2\x02\xc0T\x8d\xdf\x8e\xe2" + - "a\xfeu\x80\xd4h\xc7\x17Q<\xd2\xc9\x03XgO" + - "\x1d\xef\xfb\xef\xc5}\xa7\x9b\x9dw0\xe7\xb5\xce\x05D" + - "\x1cg\xb8\xd4S\x9d\xb7\x13@+\xb1\xe3\x0fw\xbd\xbd" + - "\xeb\xef\xaf\x04\xab%E\xbbY\xb5\x94(;\xda[\xf2" + - "/\xc8\xf0\xb9\xd2\xaf\x83\x80\xc3\xd1\xcd\x0cp\xdc\x01\xfc" + - "\xed\x7f{\x0a\x95\xde\xdf\x05\x01\xafF\xa7\x10P|\xd3" + - "\x06L/|\xf1\x1b\xdd\xebN\xff>\x08\xb8\xe1\x84X" + - "\x18c\x80\xee\xc1\xc9\xb5qu\xe3\x1f\x1b/\xc4\x01\xde" + - "\x19\xfb+\x8a\xdbb\xac\x1c\x92\x0d\xbe>\xb6\xee\xd0\xe2" + - "\xc5\xaf\x9do>\x1fa\xe8\x91\xd8J\"\x1e\xb1\xd1\x87" + - "co\x01ZGW\xed\xab\xec\xda\xdd\xf7\xa7V\xb7\xa8" + - "tu\x13\xf1K]\x0c<\xd6e\xbb\xee\xbb\xfe\xe2\xd3" + - "\xeb*\x7fn\xca\x83\xb3;\xa8\xeb,\x8a\xaf\xd8\xe03" + - "]\xecZ\xb6U6\x0a7g\xba\xfe\x12<\x95\x1c\xcf" + - "\xb0S=\x1cg\xdeV?\xb8\xf1\xf8.E\xbc\x18\x04" + - "\x1c\x8b\xbf\xc1\xea\xf2\x82\x0d\xf8\xb4\xf8\xd2\x8f\xd4#W" + - ".\x05\x01\xe7\xe3+\x99\x87\xab6\xe0\xcc\x8eT\xfa\xf5" + - "\x8b7\xbf\x0b\xc2\xa7\x88\xdfb\x80)!1\x85\xe2-" + - "\x09\x96\xcc\x8aD\x0f\xa05\xf9N\xcf\xb3\xbf\xbd\xf4\xd9" + - "\x7f\xb7\xbc\xf4\x15\x897P\x1cf\xe8\xd4`\xc2B@" + - "\xeb\x99\x91\xef~mz\xa9p\xad\xb9]\xed\x1an[" + - "\xb0\x94\x88\xd5\x05\xcc\xf9\xc8\x02V\xc3\x9f\x1d\xfd\xfaW" + - "_^\xb3\xf1Z0\xcf{E{\xa0\xaa\"\xcb\xf3\x97" + - "8\xf1\xb1\x9d{.O\x07\x01O\x89\xf6AN\xd8\x80" + - "\xe9c?H\x1d:\xf7\xfc\xfb-&nR\xbc\x89\x88" + - "WE\x1ez\xad\x9c\xa6\x965\xf5\x16\x9d7zsZ" + - "\xb9\xac\xa9\xbd\x15]3\xb5^\xc7~kN\xae\xa8\x95" + - "\xbe!\xe7\x07\xddOs\xd9\x9a\x9a\x1b\xd2TSVT" + - "\xaa/K\xcb:/\x97\x0d)\xc4\x85\x00B\x08 \xc4" + - "\xd6\x03H\x1d\x1cJI\x82\x07u:R\xa5\x86\x89\x09" + - "\xff\xf0\x80\x98\x00\x9cUX\x9dj\x15\xaan\xd1\x0a~" + - "\xdc\x0c\xed1\xaa%\xb3!\xf0f\x00)\xca\xa1\xb4\x88" + - "\xa0\xa5S\xa3\xa2\xa9\x06\x05\x00L\xf8\x14\xd6\x14<\xd2" + - "F\xf0\x8c\x1b\xc3\xa1\xb4\x95" + - "`\xdc\xacU(\xc6}\xc7\x80\x18\x07\x8cWd\xb3\x88" + - "Q \x18\x05\xba[Nxn=\x10\xe1{<" + - "\xfa\xfb\x02\xdd\xc5/\x8c?\x02D8\xc2#\xf1D " + - "\xba;C\x18{\x12\x880\xca\xa3/\xdc\xd0\xd5$B" + - "\x95\xbdW\xe61\xe4\xedJtE\xa2 \x1f\x05\"\xdc" + - "\xcbc\xd8S(\xe8\xaedA:\x0dD\xb8\x9bg\x8c" + - "\xc0.j\x00\xad\\\xbd\xfaX\xaf#\x0c\xa0\xe5\xee\x10" + - "t\xab\x8b\xfa\x00Z.G\x06\x91\xbaW\xb6:\x94\xa3" + - "\x0cj4\x94hHS\xfb\x9dW\x06p\xb6\xc4\xdc\xdc" + - "@\x01\xb2[\xee\xce\xaf\xd8\x89\xdd\x00\xd9\x10r\x98M" + - " A\xa1>\xc3b\x0c\xb7\x03d\xa3\xcc\xbe\x08\x09\"" + - "\xb1\xa7X\\\x88\x9b\x01\xb2If^\xc2\xe0\x1c&\x91" + - "\x03\x10\x17\xe3\x1a\x80\xec\"f_\xc6\xec!\x92\xc4\x10" + - "\x80\xf8I\xcc\x00d\x970\xfb:f\x0fsI\x0c\x03" + - "\x88w\xe2\x1e\x80\xec\x1d\xcc\xbe\x95\xd9#\xa1$F\x98" + - "\x1c\xb3\xc3\xa6\x99\xbd\xc4\xec|8\xc96\xbf\xa8\xd8\xf6" + - "\"\xb3?\xc6\xec\x1d\x91$v\x00\x88\xa3\xb6\xfd\x10\xb3" + - "\x7f\x8b\xd9;\xf9$v\x02\x88\xe3\xb8\x1b \xfbMf" + - "\xff\x096\x10\x8e\xb5\xbb\xaa\xe6K4-\x03\xe7\xb3\xa4" + - "eR\xbd\xac\xa8r\x89-\xd4:\xd5\xf7\x18f^Q" + - "=\xe2\xa7\xfb\x153-\x9bE@\x03\xbb\x00\xd3\x1c\xda" + - "/w\x01Z\x9aV\x1efO!.\x9b\xc5\x19OK" + - "\xee\xbcr\xba\xf7,\x11T^6*W\xa2\xb2Z\xad" + - "\x0c\x01W\xce7{(\x94\xb4\xddriP\x07\xae0" + - "\xc3;\xeb\x02Y\xcd\x0f\x02\xaf\xb7z8\xf75\x9e\xa1" + - "F\xb5\xc4\xb5+A<>l\xda\xe5\x1dmD6\x82" + - "[\xa6IG\x18\x00\x1f.$<\x96\x9d\x83\x90\xa8O" + - "s\xfb\xaa\xc5\xdb0sPz\xb9\xc6\x89\x9ce\x8d\xbd" + - "=5?\x997R\xe5\xa9\xd1,y\xba\xfd\xb3\x06g" + - "e6\x87k\xb1r|E)%\xbcX2;\xe1}" + - "\x1cJ%_1(L\x1c\xe49\x94*\x01\xc5Pf" + - "\xc6\"\x87\x92\xc9\x88f\x89M4\xc2\x08{\xbb\xc2\xa1" + - "\xf4\x10qfrH\xcb\xdb\xf5\x09\x01\xc1\x10`\xbfa" + - "\xe6\xb5\xaa\x891 \x18s~R]w\x7fZ\xa6R" + - "\xa6\xf9\xcfW\xcd\xc0\x9c\xcf\x8fS\xd9\x05q\xce\x11\x03" + - "\xe5\xdc\x13\xb8\xc4\\\x1d\x0cq=\xad\xe4\xb1\x03\x08v" + - "\xccQ\xed\xd67\xee\x07+0\xc1\x93`\xdb}\xb5%" + - "\x10\x87\xbc\x05I\x07\x90\xd2\x1cJ;\x1bo\xd9\xd0r" + - "\x0fP\xb3\x89\x11\xedEF\x0d\x03z\x14M\xdd4\xb3" + - "%\xe61\xd9v\xdb\x9b\xd8f\xdb{\xb2i\x1e\xd3=" + - "\xbbA\xf3t\xe3G\xf31\x97\x96\xe3z[\x1f\x91\x9e" + - "\x8e\x9c\xc3I]U\xa8\xdf\xba\xb5VA\xa7\x1f\xedK" + - "\x0fO\x01x=H\xf4LUe3\xb0I5\xa9~" + - "\xbf\x9cC:\xb7\xef\xa6@\xdb/\xf3\x8e\xf5\xcf\x0c\x80" + - "\xf46\x87\xd2\xb4?\xd9\xef\xb1\xa3\xbe\xcb\xa1t=0" + - "\xd9\xef/\x05\x90\xaeq\x98\xb1%\x04q&\xfb\x06\x1b" + - "\xf7i\x0e\xb3![@p\x8e\x80@& 2l\x8f" + - "Gm\xfd\x10r\xf4C'\xf65\xc8\x96H\xd8\xd1\x0f" + - "1{\xef{\xb2E\xe0#\x8e~Xh\xeb\x0d_\xb7" + - "t\xf0\x8e~Xl\xeb\x93O0\xfbr$hUt" + - "-G\x0dc\x13\xa07\xa9\xae\xe0s'\x807\xe5\x82" + - "\xfbw?\xab\x98b\x06\xb4\x85R\xcao\x90M@\xea" + - "ALY/P\x1f\xa2W\x0d\x93\x95\x11\xf8\x80O+" + - "'\xeb\x05\xed\x1e\xaaC\xdc\x98a\xde\xaa\xd3\x80\xbf\xf9" + - "r\xb2O\xff\x01Jf\x14\xb2\x93C\xa9\xe8_\x1c\xdd" + - "\xde\x8a\x92\xd7\xd7)\xf91vq\x03\xce\xc5\x8d\xb2I" + - ":\xc4\xa1\xf4\x95FZa}\xa6U\xcd,p4\xe7" + - "~~\x1e\xac\xeb\x95f\xa5\xd2B\x7f\xcdk\xb3\xb6\xbd" + - "\xce\xbd\xcf\xc29\xcc\xfa\xcc\xff\x17e\xa8\x11o\xff\xff" + - "6\xde\xe7\xe5\x1cb7}\x9a\xbbn\xd3\x88\xff\x0f\x00" + - "\x00\xff\xff\xa2\xd3\xab\xb1" +const schema_ffaaf7385bc4adad = "x\xda\xacX\x7f\x8c\x14g\xf9\x7f\x9e\xf7\xdd\xdd\xb9\xeb" + + "\xf7\xf6v\x87Y\xf2%\x17\xc9!!M\x85\xd8\xa3\x1c" + + "\xd8r\xa1\xb9;\x8e\x0b\x82Twv\xa1&PI\x87" + + "\xdd\x97\xdb\xa1\xbb3{3\xb3pKk\x80\x96\x8bi" + + "\x95*D\xa3G4)\x9a6\x82E\xac\xb5(h\x9a" + + "`\xdbhQT\xf8\xa3\x0dM\xaa\"b\x91\xd4Z\"" + + "\x8d\x87\x01\xc7\xbc3;?voM\xf7\xee\xfc\xef\xf6" + + "\x99\xcf<\xcf\xf3>\xef\xf3|\x9e\xcf\xdc\xd2\x95\xb1\x81" + + "\xc8=\xf1\x13w\x00\x91\x1f\x8b\xc6l\xf3R\xd5x\xee" + + "[k\x9f\x00q\x09\x02DQ\x00\xe8\xbd?\xba\x90\x00" + + "J\x9b\xa2\xfd\x80\xf6\xf8_?}r\xd3\x13\x7f\x7f&" + + "\x0c\xa8D\x97q\xc0\x01\x070\xb1\xe5\xea#\xc3\xeb\x12" + + "\xdf\xe6\x00\xfbz\xef\xf6\xb7'\xae\xde\xfbc\x88p\xdc" + + "\x0b\xd1k(\x9d\x8b\x0a@\xedE'^9\xff\xd4\xaa" + + "\x9eca7G\xa3s\xb8\x9b3\x8e\x9b]\x0f\xff\xf2" + + "\xc4n\xf9\xca\xf3M\xdc\\\x8a^@\xe9\xb6\xe3FZ" + + "\xb3\xf4\xd4\x1b\xbd\x8b\x8f\x83\xbc\x04\x1ba\x179\xec\x83" + + "\xa8\x00 ]w\\.?\xf2\xe2\xc9\xa7\xdf\x1b\xfb>" + + "\x07\x93\x00\xec\x06\x17c\xc7P\xfaX\xec\xff\x01\xa4{" + + "b'\x00\xedG\xcf_\xfb\xee\xd3_\x1c|\xa9\xc1\xb5" + + "\x8b~=F\x88t%\xc6}_r\xd0\xfesq\x11" + + "\xb5\x8f\x1f\x7fu\xcb}\xff\xba\xf6\xe8VU\xba\x1c" + + "\x06\\I\xbc\xc5\x0bs\xd3\x01|Bz\xe5\x07\xda\xc1" + + "kW\xc2\x80\xf9\xc9\xc5\xdc\xc3\x8a$\x07\x9c\xd9\xd2\x9b" + + "~\xf3\xf2\x9d\xef\x83\xb8\x82\x04=\x06\xd8\xbb)y\x01" + + "\xa5\xd1$O\xa6\x94\xec\x06\xb4\xcf\xbf\xd7\xfd\xfc\xaf\xae" + + "|\xea\x1fMo\xbd\x94|\x0b\xa5'9\xbawI" + + "Q\xdeH0aU\xcb\x0c\x13\x81c@L\x00&\xca" + + "\x8aU\xc0\x0e \xd8\x01\xb8\xa7\xa4\x8ce\xd5\xdd\x0c\xdb" + + "\x81`\xfb4;3\xcb\xac\xcf\xaaZ^\xdf\xc5=\xb8" + + "\xc5\xb2\x80\x17+\x94xW\x93\xc4\x975K\xbc/H" + + "\x9c\xaay/\xbf\xee]j\xde*\xa0\x00\x04\x05\xc0\xfe" + + "\x02SG\x0a\x96\xf7\xd3O6\xf2a\xc9R]\x93\x97" + + "#\x06\x1bVTv\x07\x04&*\x8f\x07;LTN" + + "\x07\xbc'\xb2L\xc0\xe7\"\xfby0\xc8\xa2z6\xd8" + + "\x0b\xe2\xe8\x85\xa0]\xc5\xaa\x11\xda\xf7\xd5\xdd\xa1]S" + + "}*$(>\x7f(\xd8\xca\xe2\xbec!\xc2\x1a\xff" + + "\xa1\xedu \xf4\xbbe\xf5\x0d\xd4\x1b\xed!\x83)\x16" + + "\xf3\xe7*\xe3\x01\x9d\xaeRw2@\xc3\xf60Q\x0f" + + "\xe4\xbd<\xdcHe\xde\xed\x81\xed=\"\xa1g\xb51" + + "\xb2\xbd\xb1\x82n7\x96\xff\xbb\xdf\xf5k{t\x81#" + + "\x81\xc3\xb0\xcds\xe4u\x0ez\xad\x93p\xfc5\x9a\xcd" + + "n\xc7\xad<\x8fF\x01\xfc\xad\x8f\xde\x96\x13_X\x0d" + + "D|V\xc0`_\xa0\xb7\xf9\xc5\x89\xc7\x81\x88\x07\x05" + + "$\xbe\x0aDog\x88\xe3\x87\x80\x88\xfb\x04\x0c\x94\x1b" + + "z\xa2D\xac\xf0\xf7J\x02F\xfc]\x89\x9eJ\x14\x95" + + "\xc3@\xc4\xcf\x09\x18\xf5%\x0az+Y\x94O\x03\x11" + + "\x1f\x108#\xf0\x8b\x1a@;W\xab>\xd6\xea\x08\x03" + + "h{;\x04\xbd\xea\xa21\x80\xb6\xc7\x91a\xa4\xe1\x97" + + "\xad\x06\xa5\x8cC\xcd\xba\x12\x0d\xe9Z\xbf\xfb\xca\x00N" + + "\x97\x98\x1b\x1b(Dvwy\xf3+\xb5c\x17@6" + + "\x82\x14\xb3I$(\xd6fX\x8a\xe3f\x80l\x07\xb7" + + "\xcfC\x82H\x9c)\x96\xe6\xe2z\x80l\x8a\x9b\x17p" + + "8\xc5\x14R\x00i>.\x03\xc8\xce\xe3\xf6E\xdc\x1e" + + "!)\x8c\x00H\x1f\xc5\x0c@v\x01\xb7\xaf\xe2\xf6(" + + "Ma\x14@Z\x89;\x00\xb2\xf7q\xfbFn\x8fE" + + "R\x18\xe3z\xcc\x09\x9b\xe6\xf6\"\xb7\x0b\xd1\x14\xdf\xfc" + + "\x92\xea\xd8\x0b\xdc\xbe\x9f\xdb\xdbb)l\x03\x90\xf69" + + "\xf6\xbd\xdc\xfeMno\x17R\xd8\x0e M\xe06\x80" + + "\xec7\xb8\xfdGXG8\xf6\xb6\x8a\x96/\xb2\xb4\x02" + + "4`I\xdbbFI\xd5\x94\"_\xa85\xaa\xef6" + + "\xad\xbc\xaa\xf9\xc4\xcf\xc6T+\xadX\x05@\x13;\x01" + + "\xd3\x14\x9d\x97;\x01m]/\x0d\xf3\xa7\x90P\xac\xc2" + + "\x94\xa7Eo^\xa9\xe1?K\x86\x95\x97\x83\xca\x15\x99" + + "\xa2U\xcaC@K\xf9F\x0f#E}\x9bR\x1c4" + + "\x80\x8eL\xf1\xce\xbb@\xd1\xf2\x83 \x18\xcd\x1e\xce|" + + "\x8dg\x98Y)\xd2V%\x88\xcf\x87\x0d\xbb\xbc\xad\x85" + + "\xc8fx\xcb4\xe8\x08\x13\xe0\xc3\x85\x84\xcf\xb23\x10" + + "\x12\xb5in]\xb5\xf8\x1bf\x06J/W?\x91\xd3" + + "\xac\xb1\xbf\xa7f'\xf3F+\x023\x1b%OWp" + + "\xd6\xf0\xacL\xe7pMVN\xa0(\xe5\xa4\x1fK\xe1" + + "'|\x98\xa2\\\x0c\x14\x83\xca\xc5A\x9e\xa2\\\x0e)" + + "\x86\x127\x16(\xca\x16'\x9a\x05\x0e\xd1\x88\xa3\xfc\xed" + + "2E\xf91\xe2\xce\xe4\x90\x9ew\xea\x13\x01\x82\x11\xc0" + + "~\xd3\xca\xeb\x15\x0b\xe3@0\xee\xfed\x86\xe1\xfd\xb4" + + "-\xb5\xc4\xf2\x9f\xa9X\xa19\x9f\x1d\xa7\xf2\x0b\xa2\xee" + + "\x11C\xe5\xdc\x11\xba\xc4\\\x0d\x0c\x09#\xad\xe6\xb1\x0d" + + "\x08\xb6\xcdP\xed\xd66nC=\xf9\xdd=DQ." + + "\x04\xf4-\xb2\xcd\xe1\x82\x92ZA\x0d\x00\xb9HQ\x1e" + + "#\x88\xd4\xadg\xe5\x10\x80\xfe\xd2J\xc2h\xe9\xa3\xd3" + + "\xd7\x9d38\xa9\xa7\"\x8d\xbb7V\xcb\xe8\xf6\xaf\xd3" + + "$\xd1\x0b\x00~\xcf\x12#S\xd1\xf8\xcc\xac\xd3,f" + + "lWr\xc8f\xf6\x9d\x15\x1a\x93E\xfe\xb1\xfe\x96\x01" + + "\x90\xdf\xa5(O\x06L\xf0\x01?\xea\xfb\x14\xe5[!" + + "&\xb8\xb9\x10@\xbeA1\xe3H\x0e\xe2v\xeemN" + + "\x0f\x93\x14\xb3\x11GpPWp \x17\x1c\x19\xbe\xf7" + + ";\x1c\xbd\x11q\xf5F;\xf6\xd5\xc9\x9cX\xd4\xd5\x1b" + + "qG'\xf82G\x14b\xae\xde\x98\xeb\xe8\x93@\xe7" + + "\xb4\x09\xae\xde\x98\xef\xe8\x99\x8fp\xfb]H\xd0.\x1b" + + "z\x8e\x99\xe6:@\x7f\xb2=\x81\xe8M\x87`)#" + + "\xde\xdf\xfd\xbcb\xaa\x15\xd2\"j1\xbfF\xb1\x00\x99" + + "\x0f\xb1\x14c\x84\x05\x10\xa3bZ\xbc\x8c \x84|\xda" + + "9\xc5\x18\xd1\x1fd\x06$\xcc)\xe6\x8d\x06\x0b\xf9\x9b" + + "-\x87\x07\xeb\xa29\xe54g\x1c\x8f\xc2W\xd7(|" + + "?\xbf\xb8\x01\xf7\xe2\xf6\xf1I\xdaKQ\xfeR=\xe5" + + "\xf0>\xd3+V\x16(\xcby\x9f\xab{j\xfa\xa6Q" + + "\xd94\xd1k\xb3\xda\xc4-\xaf\x7f\xff3r\x06\xb3>" + + "\xf5\xffK\x19f&Z\xff?\x8f\xff9:\x83\xd8\x0d" + + "\x9f\xf2\x9e\xdb4\xe2\x7f\x02\x00\x00\xff\xff\"q\xb9\x88" func init() { schemas.Register(schema_ffaaf7385bc4adad, diff --git a/pkg/client/attach.go b/pkg/client/attach.go index 852941eca5..5e7cb178b0 100644 --- a/pkg/client/attach.go +++ b/pkg/client/attach.go @@ -66,6 +66,9 @@ type AttachConfig struct { // Whether stdout/stderr should continue to be processed after stdin is closed. StopAfterStdinEOF bool + // Whether the container supports stdin or not. + ContainerStdin bool + // Whether the output is passed through the caller's std streams, rather than // ones created for the attach session. Passthrough bool @@ -121,6 +124,8 @@ func (c *ConmonClient) AttachContainer(ctx context.Context, cfg *AttachConfig) e return fmt.Errorf("set socket path: %w", err) } + req.SetStopAfterStdinEof(cfg.StopAfterStdinEOF) + // TODO: add exec session return nil }) @@ -244,7 +249,7 @@ func (c *ConmonClient) redirectResponseToOutputStreams(cfg *AttachConfig, conn i return nil } } - if er == io.EOF { + if er == io.EOF || (cfg.ContainerStdin && !cfg.StopAfterStdinEOF) { return nil } if errors.Is(er, syscall.ECONNRESET) { diff --git a/pkg/client/client_test.go b/pkg/client/client_test.go index 3f1bc02ebb..0fc3da25ab 100644 --- a/pkg/client/client_test.go +++ b/pkg/client/client_test.go @@ -450,8 +450,9 @@ var _ = Describe("ConmonClient", func() { stdReader, stdWriter := io.Pipe() cfg := &client.AttachConfig{ - ID: tr.ctrID, - SocketPath: filepath.Join(tr.tmpDir, "attach"), + ID: tr.ctrID, + SocketPath: filepath.Join(tr.tmpDir, "attach"), + StopAfterStdinEOF: true, Streams: client.AttachStreams{ Stdin: &client.In{stdinReader}, },