# How ProcessService Manages Core Processes on Different Platforms in v2rayN

> Understand how v2rayN's ProcessService manages core processes like v2ray and Xray across Windows, Linux, and macOS. Learn about cross-platform execution and privilege handling for stability.

- Repository: [2dust/v2rayN](https://github.com/2dust/v2rayN)
- Tags: internals
- Published: 2026-02-27

---

**ProcessService is the low-level execution wrapper in v2rayN that standardizes how v2ray, Xray, sing-box, and mihomo core binaries are launched, monitored, and terminated across Windows, Linux, and macOS, with specialized handling for elevated privileges on Unix-like systems.**

The `ProcessService` class provides the foundational abstraction layer for process lifecycle management in the v2rayN proxy client. According to the source code in `2dust/v2rayN`, this service integrates with **CoreManager** and **CoreAdminManager** to handle platform-specific requirements ranging from Windows Job Objects to Linux sudo authentication pipelines.

## Platform-Aware Launch Flow

The execution path selection begins in `CoreManager.RunProcess`, which evaluates the operating system, Tun mode configuration, and core type to determine whether to use standard execution or privilege-escalated workflows.

### Windows Normal Execution

On Windows systems, standard core launches proceed through `CoreManager.RunProcessNormal`. This method instantiates a new `ProcessService` with the binary path and arguments, then immediately registers the resulting process handle with the `WindowsJobService`. This registration binds the core process to a Windows Job Object, ensuring automatic cleanup if the parent v2rayN application terminates unexpectedly.

### Linux and macOS Normal Execution

For non-Windows platforms without privilege requirements, `RunProcessNormal` follows the same instantiation pattern but omits the Job Object registration. Instead, `ProcessService.StopAsync` implements recursive termination logic using `_process.Kill(true)` to eliminate child processes before killing the parent, preventing orphaned processes on Unix-like systems.

### Elevated Privileges on Unix-like Systems

When Tun mode is enabled on Linux or macOS for sing-box or mihomo cores, the system requires root privileges to configure network interfaces. In this scenario, `CoreManager` delegates execution to `CoreAdminManager.RunProcessAsLinuxSudo`:

```csharp
// CoreManager.cs – RunProcess (lines 22-44)
if (mayNeedSudo && _config.TunModeItem.EnableTun &&
    (coreInfo.CoreType is ECoreType.sing_box or ECoreType.mihomo) &&
    Utils.IsNonWindows())
{
    _linuxSudo = true;
    await CoreAdminManager.Instance.Init(_config, _updateFunc);
    return await CoreAdminManager.Instance.RunProcessAsLinuxSudo(fileName, coreInfo, configPath);
}
else
{
    return await RunProcessNormal(fileName, coreInfo, configPath, displayLog);
}

```

This conditional branch triggers the generation of temporary bash scripts that wrap the core execution with `sudo -S`, enabling secure password authentication via standard input rather than command-line arguments.

## ProcessService Architecture

Located in [`ServiceLib/Services/ProcessService.cs`](https://github.com/2dust/v2rayN/blob/main/ServiceLib/Services/ProcessService.cs), the class provides a unified interface for external process management with distinct lifecycle stages.

### Construction and Configuration

The constructor (lines 13-21) initializes `ProcessStartInfo` with the specified filename, arguments, working directory, and stream redirection options. This configuration supports both standard executions and sudo workflows requiring stdin access for password input.

### Asynchronous Process Starting

`StartAsync` (lines 56-71) executes `Process.Start()` and initiates asynchronous reading of stdout and stderr streams. For privilege-escalated launches, the method accepts an optional password parameter:

```csharp
// ProcessService.StartAsync implementation detail
if (!string.IsNullOrEmpty(pwd))
{
    await _process.StandardInput.WriteLineAsync(pwd);
    await _process.StandardInput.FlushAsync();
}

```

This writes the sudo password directly to the process's standard input stream, satisfying the `sudo -S` requirement without exposing credentials in process listings.

### Cross-Platform Termination

`StopAsync` (lines 96-108) implements platform-specific termination logic. On non-Windows systems, it first invokes `_process.Kill(true)` to send termination signals to the entire process tree, followed by `_process.Kill()` for the parent. Windows implementations call `Kill()` directly, relying on the previously mentioned Job Object for child process cleanup.

### Resource Disposal

The `Dispose` method (lines 52-70) guarantees process termination and handle release, again utilizing the recursive kill approach on Linux and macOS to ensure complete cleanup of spawned helper processes.

## Windows Job Object Integration

Windows-specific durability features leverage `WindowsJobService` to bind core processes to a Job Object with the `JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE` flag (`0x2000`). This kernel-level association ensures that if the v2rayN GUI crashes or closes normally, the operating system automatically terminates all associated core processes.

```csharp
// CoreManager.cs – AddProcessJob (lines 85-86)
if (Utils.IsWindows())
{
    _processJob ??= new();
    _processJob?.AddProcess(processHandle);
}

```

The `WindowsJobService` (lines 12-18) wraps native Windows APIs including `CreateJobObject` and `AssignProcessToJobObject`, providing a managed interface for this functionality.

## Linux and macOS Sudo Handling

Privileged execution on Unix-like systems requires generating temporary shell scripts to interface securely with the sudo system.

### Starting with Sudo

`CoreAdminManager.RunProcessAsLinuxSudo` constructs a bash script that executes the core binary with elevated privileges:

```csharp
// CoreAdminManager.cs – RunProcessAsLinuxSudo (lines 34-48)
sb.AppendLine("#!/bin/bash");
var cmdLine = $"{fileName.AppendQuotes()} {string.Format(coreInfo.Arguments, Utils.GetBinConfigPath(configPath).AppendQuotes())}";
sb.AppendLine($"exec sudo -S -- {cmdLine}");
var shFilePath = await FileUtils.CreateLinuxShellFile("run_as_sudo.sh", sb.ToString(), true);

var procService = new ProcessService(
    fileName: shFilePath,
    arguments: "",
    redirectInput: true,
    ...);
await procService.StartAsync(AppManager.Instance.LinuxSudoPwd);

```

### Stopping Sudo Processes

Termination requires equivalent privilege escalation. `CoreAdminManager.KillProcessAsLinuxSudo` creates [`kill_as_sudo.sh`](https://github.com/2dust/v2rayN/blob/main/kill_as_sudo.sh) containing the appropriate kill commands, executed via `sudo -S` with the stored password piped through `ProcessService.StartAsync` (lines 61-81 in [`CoreAdminManager.cs`](https://github.com/2dust/v2rayN/blob/main/CoreAdminManager.cs)).

## Practical Code Examples

### Standard Core Launch

```csharp
var coreInfo = CoreInfoManager.Instance.GetCoreInfo(ECoreType.Xray);
var procService = await CoreManager.Instance.RunProcessNormal(
    fileName: CoreInfoManager.Instance.GetCoreExecFile(coreInfo, out _),
    coreInfo: coreInfo,
    configPath: "config.json",
    displayLog: true);

await procService.StartAsync();

```

### Elevated Launch on Linux

```csharp
// Automatically handled by CoreManager when Tun mode is enabled
var procService = await CoreAdminManager.Instance.RunProcessAsLinuxSudo(
    fileName: "/usr/local/bin/sing-box",
    coreInfo: coreInfo,
    configPath: "config.json");

await procService.StartAsync(AppManager.Instance.LinuxSudoPwd);

```

### Stopping a Core Process

```csharp
await procService.StopAsync();  // Handles child processes on Linux/macOS
procService.Dispose();          // Ensures complete resource cleanup

```

## Summary

- **ProcessService** provides a unified abstraction for launching v2ray, Xray, sing-box, and mihomo cores across Windows, Linux, and macOS without platform-specific code in the consumer layers.
- **Windows** utilizes Job Objects via `WindowsJobService` with the `JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE` flag to guarantee automatic process tree cleanup when the parent application exits.
- **Linux and macOS** employ `_process.Kill(true)` in `StopAsync` to recursively terminate child processes, preventing zombie processes when killing the core binary.
- **Elevated execution** on Unix-like systems generates temporary bash scripts ([`run_as_sudo.sh`](https://github.com/2dust/v2rayN/blob/main/run_as_sudo.sh), [`kill_as_sudo.sh`](https://github.com/2dust/v2rayN/blob/main/kill_as_sudo.sh)) and securely pipes passwords via `StartAsync` when Tun mode requires root privileges.
- **CoreManager** orchestrates the platform detection logic, delegating to `CoreAdminManager` only when `mayNeedSudo`, `EnableTun`, and `IsNonWindows` conditions converge.

## Frequently Asked Questions

### How does v2rayN prevent orphaned core processes when the application crashes on Windows?

v2rayN uses the `WindowsJobService` to create a Windows Job Object with the `JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE` flag. When `CoreManager.AddProcessJob` registers the core process handle to this job, the Windows kernel guarantees that all processes in the job terminate automatically if the parent v2rayN process closes unexpectedly.

### Why does ProcessService use different kill strategies on Linux versus Windows?

On Windows, the Job Object handles process tree cleanup automatically, so `ProcessService.StopAsync` calls `Kill()` directly. On Linux and macOS, `StopAsync` first calls `_process.Kill(true)` to recursively signal child processes before killing the parent. This approach prevents zombie processes and ensures that spawned helper processes created by sing-box or mihomo are properly terminated.

### What triggers the sudo workflow in v2rayN's process management?

The sudo workflow activates when three conditions are met simultaneously: the configuration enables Tun mode (`_config.TunModeItem.EnableTun`), the selected core type is either sing-box or mihomo, and the operating system is non-Windows (`Utils.IsNonWindows()`). When these conditions are satisfied, `CoreManager.RunProcess` delegates to `CoreAdminManager.RunProcessAsLinuxSudo` instead of the standard execution path.

### How is the sudo password securely transmitted to the core process?

The password is never passed as a command-line argument where it could appear in process listings. Instead, `CoreAdminManager` creates a temporary bash script that invokes `sudo -S`, which reads the password from standard input. The `ProcessService.StartAsync` method receives the password as a parameter and writes it to `StandardInput` immediately after process creation, allowing secure authentication without exposing credentials.