mirror of
https://github.com/microsoft/vscode.git
synced 2026-04-24 02:28:34 +01:00
cli: use win32 app mutex to detect running tunnels and tunnel sevices (#179622)
* cli: fix distro mixin * cli: use win32 app mutex to detect running tunnels and tunnel sevices Fixes #179265 * cli: fix distro mixin more * fix * fix build
This commit is contained in:
58
cli/src/util/app_lock.rs
Normal file
58
cli/src/util/app_lock.rs
Normal file
@@ -0,0 +1,58 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
#[cfg(windows)]
|
||||
use std::{io, ptr};
|
||||
|
||||
#[cfg(windows)]
|
||||
use winapi::{
|
||||
shared::winerror::ERROR_ALREADY_EXISTS,
|
||||
um::{handleapi::CloseHandle, synchapi::CreateMutexA, winnt::HANDLE},
|
||||
};
|
||||
|
||||
use super::errors::CodeError;
|
||||
|
||||
pub struct AppMutex {
|
||||
#[cfg(windows)]
|
||||
handle: HANDLE,
|
||||
}
|
||||
|
||||
#[cfg(windows)] // handle is thread-safe, mark it so with this
|
||||
unsafe impl Send for AppMutex {}
|
||||
|
||||
impl AppMutex {
|
||||
#[cfg(unix)]
|
||||
pub fn new(_name: &str) -> Result<Self, CodeError> {
|
||||
Ok(Self {})
|
||||
}
|
||||
|
||||
#[cfg(windows)]
|
||||
pub fn new(name: &str) -> Result<Self, CodeError> {
|
||||
let handle = unsafe { CreateMutexA(ptr::null_mut(), 0, name.as_ptr() as _) };
|
||||
|
||||
if !handle.is_null() {
|
||||
return Ok(Self { handle });
|
||||
}
|
||||
|
||||
let err = io::Error::last_os_error();
|
||||
let raw = err.raw_os_error();
|
||||
// docs report it should return ERROR_IO_PENDING, but in my testing it actually
|
||||
// returns ERROR_LOCK_VIOLATION. Or maybe winapi is wrong?
|
||||
if raw == Some(ERROR_ALREADY_EXISTS as i32) {
|
||||
return Err(CodeError::AppAlreadyLocked(name.to_string()));
|
||||
}
|
||||
|
||||
Err(CodeError::AppLockFailed(err))
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for AppMutex {
|
||||
fn drop(&mut self) {
|
||||
#[cfg(windows)]
|
||||
unsafe {
|
||||
CloseHandle(self.handle)
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -494,6 +494,12 @@ pub enum CodeError {
|
||||
NoRunningTunnel,
|
||||
#[error("rpc call failed: {0:?}")]
|
||||
TunnelRpcCallFailed(ResponseError),
|
||||
#[cfg(windows)]
|
||||
#[error("the windows app lock {0} already exists")]
|
||||
AppAlreadyLocked(String),
|
||||
#[cfg(windows)]
|
||||
#[error("could not get windows app lock: {0:?}")]
|
||||
AppLockFailed(std::io::Error),
|
||||
}
|
||||
|
||||
makeAnyError!(
|
||||
|
||||
Reference in New Issue
Block a user