краш фикс (vibe-kanban fd9bb887)
Сейчас реализовано подключение к vpn через конфиг. В папке bin лежит sing-box.exe. При нажатии подключить - включается прокси в windows как положено и происходит краш программы: PS C:\\Users\\hamy\\HamyDev\\HamyVPNClient\\HamyVPNClient> go run . 2026/01/16 19:53:28 Sing-box configuration written to config.json Exception 0xc0000005 0x1 0x1 0x7ffbb351b5d5 PC=0x7ffbb351b5d5 signal arrived during external code execution
This commit is contained in:
22
config.json
Normal file
22
config.json
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
{
|
||||||
|
"log": {
|
||||||
|
"level": "info"
|
||||||
|
},
|
||||||
|
"inbounds": [
|
||||||
|
{
|
||||||
|
"type": "mixed",
|
||||||
|
"listen": "127.0.0.1",
|
||||||
|
"listen_port": 1080,
|
||||||
|
"set_system_proxy": true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"outbounds": [
|
||||||
|
{
|
||||||
|
"type": "vless",
|
||||||
|
"server": "193.124.93.179",
|
||||||
|
"server_port": 39590,
|
||||||
|
"uuid": "3da694cb-cca3-4849-81c3-9ff60c4dc399",
|
||||||
|
"network": "tcp"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
Binary file not shown.
73
main.go
73
main.go
@@ -13,6 +13,7 @@ import (
|
|||||||
"regexp"
|
"regexp"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
"sync"
|
||||||
"syscall"
|
"syscall"
|
||||||
"unsafe"
|
"unsafe"
|
||||||
|
|
||||||
@@ -36,6 +37,7 @@ type Config struct {
|
|||||||
|
|
||||||
var (
|
var (
|
||||||
currentProcess *exec.Cmd
|
currentProcess *exec.Cmd
|
||||||
|
processMutex sync.Mutex // Mutex to protect process operations
|
||||||
configs []Config // Store all configurations
|
configs []Config // Store all configurations
|
||||||
activeConfig int // Index of the active config (-1 if none)
|
activeConfig int // Index of the active config (-1 if none)
|
||||||
configFilePath string = "configs.json" // Path to save/load configs
|
configFilePath string = "configs.json" // Path to save/load configs
|
||||||
@@ -164,6 +166,18 @@ func runSingBox(configPath string) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Acquire lock to prevent concurrent process operations
|
||||||
|
processMutex.Lock()
|
||||||
|
defer processMutex.Unlock()
|
||||||
|
|
||||||
|
// Kill any existing process before starting a new one
|
||||||
|
if currentProcess != nil && currentProcess.Process != nil {
|
||||||
|
// Attempt to terminate gracefully first
|
||||||
|
currentProcess.Process.Kill()
|
||||||
|
currentProcess.Wait() // Wait for graceful termination
|
||||||
|
currentProcess = nil
|
||||||
|
}
|
||||||
|
|
||||||
cmd := exec.Command(singBoxPath, "run", "-c", configPath)
|
cmd := exec.Command(singBoxPath, "run", "-c", configPath)
|
||||||
|
|
||||||
// Make the process run as hidden
|
// Make the process run as hidden
|
||||||
@@ -177,13 +191,45 @@ func runSingBox(configPath string) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
currentProcess = cmd
|
currentProcess = cmd
|
||||||
|
|
||||||
|
// Start a goroutine to wait for the process to finish
|
||||||
|
go func() {
|
||||||
|
cmd.Wait()
|
||||||
|
// Clear the process reference when it finishes
|
||||||
|
processMutex.Lock()
|
||||||
|
if currentProcess == cmd {
|
||||||
|
currentProcess = nil
|
||||||
|
}
|
||||||
|
processMutex.Unlock()
|
||||||
|
}()
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// isProcessRunning checks if the process is still running
|
||||||
|
func isProcessRunning(cmd *exec.Cmd) bool {
|
||||||
|
if cmd == nil || cmd.Process == nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// On Windows, check if the process is still alive by getting its state
|
||||||
|
err := cmd.Process.Signal(syscall.Signal(0))
|
||||||
|
return err == nil
|
||||||
|
}
|
||||||
|
|
||||||
// killCurrentProcess terminates the current sing-box process if running
|
// killCurrentProcess terminates the current sing-box process if running
|
||||||
func killCurrentProcess() {
|
func killCurrentProcess() {
|
||||||
|
processMutex.Lock()
|
||||||
|
defer processMutex.Unlock()
|
||||||
|
|
||||||
if currentProcess != nil && currentProcess.Process != nil {
|
if currentProcess != nil && currentProcess.Process != nil {
|
||||||
|
// Check if the process is still running before attempting to kill it
|
||||||
|
if isProcessRunning(currentProcess) {
|
||||||
|
// Use TerminateProcess syscall for more reliable termination on Windows
|
||||||
currentProcess.Process.Kill()
|
currentProcess.Process.Kill()
|
||||||
|
// Wait for the process to actually terminate
|
||||||
|
currentProcess.Wait()
|
||||||
|
}
|
||||||
currentProcess = nil
|
currentProcess = nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -452,8 +498,13 @@ func generateConfigFromVLESSURL(vlessURL, outputPath string) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var proxyMutex sync.Mutex // Mutex to protect proxy operations
|
||||||
|
|
||||||
// setSystemProxy enables the system proxy with the specified server and port
|
// setSystemProxy enables the system proxy with the specified server and port
|
||||||
func setSystemProxy(proxyServer string) error {
|
func setSystemProxy(proxyServer string) error {
|
||||||
|
proxyMutex.Lock()
|
||||||
|
defer proxyMutex.Unlock()
|
||||||
|
|
||||||
key, err := registry.OpenKey(registry.CURRENT_USER, `Software\Microsoft\Windows\CurrentVersion\Internet Settings`, registry.SET_VALUE)
|
key, err := registry.OpenKey(registry.CURRENT_USER, `Software\Microsoft\Windows\CurrentVersion\Internet Settings`, registry.SET_VALUE)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("failed to open registry key: %v", err)
|
return fmt.Errorf("failed to open registry key: %v", err)
|
||||||
@@ -486,6 +537,9 @@ func setSystemProxy(proxyServer string) error {
|
|||||||
|
|
||||||
// disableSystemProxy disables the system proxy
|
// disableSystemProxy disables the system proxy
|
||||||
func disableSystemProxy() error {
|
func disableSystemProxy() error {
|
||||||
|
proxyMutex.Lock()
|
||||||
|
defer proxyMutex.Unlock()
|
||||||
|
|
||||||
key, err := registry.OpenKey(registry.CURRENT_USER, `Software\Microsoft\Windows\CurrentVersion\Internet Settings`, registry.SET_VALUE)
|
key, err := registry.OpenKey(registry.CURRENT_USER, `Software\Microsoft\Windows\CurrentVersion\Internet Settings`, registry.SET_VALUE)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("failed to open registry key: %v", err)
|
return fmt.Errorf("failed to open registry key: %v", err)
|
||||||
@@ -594,12 +648,18 @@ func main() {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Prevent multiple simultaneous connection attempts
|
||||||
|
connectButton.Disable()
|
||||||
|
defer connectButton.Enable() // Re-enable the button after the operation completes
|
||||||
|
|
||||||
// Toggle connection state
|
// Toggle connection state
|
||||||
if !isConnected {
|
if !isConnected {
|
||||||
// Connect - generate config and run sing-box
|
// Connect - generate config and run sing-box
|
||||||
err := generateAndRunSingBox(configs[activeConfig].URL)
|
err := generateAndRunSingBox(configs[activeConfig].URL)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
log.Printf("Failed to start connection: %v", err)
|
||||||
dialog.ShowError(fmt.Errorf("failed to start connection: %v", err), myWindow)
|
dialog.ShowError(fmt.Errorf("failed to start connection: %v", err), myWindow)
|
||||||
|
|
||||||
// Revert connection state on failure
|
// Revert connection state on failure
|
||||||
isConnected = false
|
isConnected = false
|
||||||
updateConnectionButtonText(connectButton)
|
updateConnectionButtonText(connectButton)
|
||||||
@@ -614,6 +674,15 @@ func main() {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("Failed to set system proxy: %v", err)
|
log.Printf("Failed to set system proxy: %v", err)
|
||||||
dialog.ShowError(fmt.Errorf("failed to set system proxy: %v", err), myWindow)
|
dialog.ShowError(fmt.Errorf("failed to set system proxy: %v", err), myWindow)
|
||||||
|
|
||||||
|
// If proxy failed to set, kill the sing-box process and revert connection
|
||||||
|
killCurrentProcess()
|
||||||
|
isConnected = false
|
||||||
|
updateConnectionButtonText(connectButton)
|
||||||
|
statusLabel.Text = "Отключено"
|
||||||
|
statusLabel.Color = color.RGBA{R: 128, G: 128, B: 128, A: 255}
|
||||||
|
statusLabel.Refresh()
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update connection state after successful connection
|
// Update connection state after successful connection
|
||||||
@@ -808,9 +877,7 @@ func main() {
|
|||||||
// Register an app lifecycle listener to handle cleanup when the app exits
|
// Register an app lifecycle listener to handle cleanup when the app exits
|
||||||
myApp.Lifecycle().SetOnStopped(func() {
|
myApp.Lifecycle().SetOnStopped(func() {
|
||||||
// Kill the current process if running
|
// Kill the current process if running
|
||||||
if currentProcess != nil && currentProcess.Process != nil {
|
killCurrentProcess()
|
||||||
currentProcess.Process.Kill()
|
|
||||||
}
|
|
||||||
|
|
||||||
// Disable proxy when the application exits
|
// Disable proxy when the application exits
|
||||||
err := disableSystemProxy()
|
err := disableSystemProxy()
|
||||||
|
|||||||
Reference in New Issue
Block a user