Skip to content

Commit c618860

Browse files
aeschliconnor4312
andauthored
tunnel cli: add --parent-process-id option (microsoft#163935)
* tunnel cli: add --parent-process-id option * Update cli/src/commands/args.rs Co-authored-by: Connor Peet <[email protected]> * Change parent process check interval to 2s Co-authored-by: Connor Peet <[email protected]>
1 parent 5e170fc commit c618860

File tree

5 files changed

+47
-12
lines changed

5 files changed

+47
-12
lines changed

cli/src/commands/args.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -559,6 +559,10 @@ pub struct TunnelServeArgs {
559559
/// Randomly name machine for port forwarding service
560560
#[clap(long)]
561561
pub random_name: bool,
562+
563+
/// Optional parent process id. If provided, the server will be stopped when the process of the given pid no longer exists
564+
#[clap(long, hide = true)]
565+
pub parent_process_id: Option<i32>,
562566
}
563567

564568
#[derive(Args, Debug, Clone)]

cli/src/commands/tunnels.rs

Lines changed: 34 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,11 @@
33
* Licensed under the MIT License. See License.txt in the project root for license information.
44
*--------------------------------------------------------------------------------------------*/
55

6+
use std::fmt;
67
use async_trait::async_trait;
7-
use tokio::sync::oneshot;
8+
use sysinfo::{Pid, SystemExt};
9+
use tokio::sync::mpsc;
10+
use tokio::time::{sleep, Duration};
811

912
use super::{
1013
args::{
@@ -70,7 +73,7 @@ impl ServiceContainer for TunnelServiceContainer {
7073
&mut self,
7174
log: log::Logger,
7275
launcher_paths: LauncherPaths,
73-
shutdown_rx: oneshot::Receiver<()>,
76+
shutdown_rx: mpsc::Receiver<ShutdownSignal>,
7477
) -> Result<(), AnyError> {
7578
let csa = (&self.args).into();
7679
serve_with_csa(
@@ -87,6 +90,20 @@ impl ServiceContainer for TunnelServiceContainer {
8790
Ok(())
8891
}
8992
}
93+
/// Describes the signal to manully stop the server
94+
pub enum ShutdownSignal {
95+
CtrlC,
96+
ParentProcessKilled,
97+
}
98+
99+
impl fmt::Display for ShutdownSignal {
100+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
101+
match self {
102+
ShutdownSignal::CtrlC => write!(f, "Ctrl-C received"),
103+
ShutdownSignal::ParentProcessKilled => write!(f, "Parent process no longer exists"),
104+
}
105+
}
106+
}
90107

91108
pub async fn service(
92109
ctx: CommandContext,
@@ -211,7 +228,7 @@ async fn serve_with_csa(
211228
log: Logger,
212229
gateway_args: TunnelServeArgs,
213230
csa: CodeServerArgs,
214-
shutdown_rx: Option<oneshot::Receiver<()>>,
231+
shutdown_rx: Option<mpsc::Receiver<ShutdownSignal>>,
215232
) -> Result<i32, AnyError> {
216233
// Intentionally read before starting the server. If the server updated and
217234
// respawn is requested, the old binary will get renamed, and then
@@ -230,10 +247,22 @@ async fn serve_with_csa(
230247
let shutdown_tx = if let Some(tx) = shutdown_rx {
231248
tx
232249
} else {
233-
let (tx, rx) = oneshot::channel();
250+
let (tx, rx) = mpsc::channel::<ShutdownSignal>(2);
251+
if let Some(process_id) = gateway_args.parent_process_id {
252+
let tx = tx.clone();
253+
info!(log, "checking for parent process {}", process_id);
254+
tokio::spawn(async move {
255+
let mut s = sysinfo::System::new();
256+
let pid = Pid::from(process_id);
257+
while s.refresh_process(pid) {
258+
sleep(Duration::from_millis(2000)).await;
259+
}
260+
tx.send(ShutdownSignal::ParentProcessKilled).await.ok();
261+
});
262+
}
234263
tokio::spawn(async move {
235264
tokio::signal::ctrl_c().await.ok();
236-
tx.send(()).ok();
265+
tx.send(ShutdownSignal::CtrlC).await.ok();
237266
});
238267
rx
239268
};

cli/src/tunnels/control_server.rs

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
* Copyright (c) Microsoft Corporation. All rights reserved.
33
* Licensed under the MIT License. See License.txt in the project root for license information.
44
*--------------------------------------------------------------------------------------------*/
5+
use crate::commands::tunnels::ShutdownSignal;
56
use crate::constants::{CONTROL_PORT, PROTOCOL_VERSION, VSCODE_CLI_VERSION};
67
use crate::log;
78
use crate::self_update::SelfUpdate;
@@ -23,7 +24,7 @@ use std::sync::Arc;
2324
use std::time::Instant;
2425
use tokio::io::{AsyncRead, AsyncReadExt, AsyncWrite, AsyncWriteExt, BufReader};
2526
use tokio::pin;
26-
use tokio::sync::{mpsc, oneshot, Mutex};
27+
use tokio::sync::{mpsc, Mutex};
2728

2829
use super::code_server::{
2930
AnyCodeServer, CodeServerArgs, ServerBuilder, ServerParamsRaw, SocketCodeServer,
@@ -181,7 +182,7 @@ pub async fn serve(
181182
launcher_paths: &LauncherPaths,
182183
code_server_args: &CodeServerArgs,
183184
platform: Platform,
184-
shutdown_rx: oneshot::Receiver<()>,
185+
shutdown_rx: mpsc::Receiver<ShutdownSignal>,
185186
) -> Result<ServerTermination, AnyError> {
186187
let mut port = tunnel.add_port_direct(CONTROL_PORT).await?;
187188
print_listening(log, &tunnel.name);
@@ -194,8 +195,8 @@ pub async fn serve(
194195

195196
loop {
196197
tokio::select! {
197-
_ = &mut shutdown_rx => {
198-
info!(log, "Received interrupt, shutting down...");
198+
Some(r) = shutdown_rx.recv() => {
199+
info!(log, "Shutting down: {}", r );
199200
drop(signal_exit);
200201
return Ok(ServerTermination {
201202
respawn: false,

cli/src/tunnels/service.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,9 @@
66
use std::path::PathBuf;
77

88
use async_trait::async_trait;
9-
use tokio::sync::oneshot;
9+
use tokio::sync::mpsc;
1010

11+
use crate::commands::tunnels::ShutdownSignal;
1112
use crate::log;
1213
use crate::state::LauncherPaths;
1314
use crate::util::errors::AnyError;
@@ -20,7 +21,7 @@ pub trait ServiceContainer: Send {
2021
&mut self,
2122
log: log::Logger,
2223
launcher_paths: LauncherPaths,
23-
shutdown_rx: oneshot::Receiver<()>,
24+
shutdown_rx: mpsc::Receiver<ShutdownSignal>,
2425
) -> Result<(), AnyError>;
2526
}
2627

src/vs/platform/remoteTunnel/electron-browser/remoteTunnelService.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -145,7 +145,7 @@ export class RemoteTunnelService extends Disposable implements IRemoteTunnelServ
145145
hostName = undefined;
146146
}
147147
}
148-
const args = hostName ? [] : ['--random-name'];
148+
const args = hostName ? [] : ['--random-name', '--parent-process-id', String(process.pid)];
149149
const serveCommand = this.runCodeTunneCommand('tunnel', args, (message: string) => {
150150
});
151151
this._tunnelProcess = serveCommand;

0 commit comments

Comments
 (0)