diff --git a/configs.json b/configs.json new file mode 100644 index 0000000..43fde6a --- /dev/null +++ b/configs.json @@ -0,0 +1,6 @@ +[ + { + "Title": "Конфиг 1", + "URL": "vless://3da694cb-cca3-4849-81c3-9ff60c4dc399@193.124.93.179:39590?type=tcp\u0026encryption=none\u0026security=none#TCP%20HamyVPN-TEST2" + } +] \ No newline at end of file diff --git a/hamy-vpn-client-fixed.exe b/hamy-vpn-client-fixed.exe index 96c162a..3341f57 100644 Binary files a/hamy-vpn-client-fixed.exe and b/hamy-vpn-client-fixed.exe differ diff --git a/main.go b/main.go index 10328b4..f8afe79 100644 --- a/main.go +++ b/main.go @@ -174,7 +174,10 @@ func runSingBox(configPath string) error { if currentProcess != nil && currentProcess.Process != nil { // Attempt to terminate gracefully first currentProcess.Process.Kill() - currentProcess.Wait() // Wait for graceful termination + // Wait for the process to finish in a separate goroutine to avoid blocking + go func(p *exec.Cmd) { + p.Wait() // Wait for graceful termination + }(currentProcess) currentProcess = nil } @@ -213,6 +216,7 @@ func isProcessRunning(cmd *exec.Cmd) bool { } // On Windows, check if the process is still alive by getting its state + // Using syscall.Signal(0) just checks if we can send a signal (process exists) err := cmd.Process.Signal(syscall.Signal(0)) return err == nil } @@ -220,17 +224,27 @@ func isProcessRunning(cmd *exec.Cmd) bool { // killCurrentProcess terminates the current sing-box process if running func killCurrentProcess() { processMutex.Lock() - defer processMutex.Unlock() - if currentProcess != nil && currentProcess.Process != nil { + // Create a local copy of the current process to avoid race conditions + cmd := currentProcess + currentProcess = nil + + processMutex.Unlock() + + if cmd != nil && cmd.Process != nil { // Check if the process is still running before attempting to kill it - if isProcessRunning(currentProcess) { + if isProcessRunning(cmd) { // Use TerminateProcess syscall for more reliable termination on Windows - currentProcess.Process.Kill() - // Wait for the process to actually terminate - currentProcess.Wait() + err := cmd.Process.Kill() + if err != nil { + log.Printf("Error killing process: %v", err) + } + + // Wait for the process to actually terminate in a separate goroutine to avoid blocking + go func(p *exec.Cmd) { + p.Wait() // Wait for the process to finish + }(cmd) } - currentProcess = nil } } @@ -562,24 +576,34 @@ func disableSystemProxy() error { func notifyProxyChange() { // Use Windows API to notify about proxy change // Call InternetSetOption to refresh proxy settings - procInternetSetOption := syscall.NewLazyDLL("wininet.dll").NewProc("InternetSetOptionW") - procInternetSetOption.Call( - 0, // hInternet = NULL - 39, // INTERNET_OPTION_SETTINGS_CHANGED - 0, // lpBuffer = NULL - 0, // dwBufferLength = 0 - ) + wininetDLL := syscall.NewLazyDLL("wininet.dll") + if wininetDLL != nil { + procInternetSetOption := wininetDLL.NewProc("InternetSetOptionW") + if procInternetSetOption != nil { + procInternetSetOption.Call( + 0, // hInternet = NULL + 39, // INTERNET_OPTION_SETTINGS_CHANGED + 0, // lpBuffer = NULL + 0, // dwBufferLength = 0 + ) + } + } // Also send WM_SETTINGCHANGE to broadcast the change - procSendMessageTimeout := syscall.NewLazyDLL("user32.dll").NewProc("SendMessageTimeoutW") - procSendMessageTimeout.Call( - 0xFFFF, // HWND_BROADCAST - 0x001A, // WM_SETTINGCHANGE - uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr("Proxy"))), - 0, - 0x0002, // SMTO_ABORTIFHUNG - 5000, // timeout - ) + user32DLL := syscall.NewLazyDLL("user32.dll") + if user32DLL != nil { + procSendMessageTimeout := user32DLL.NewProc("SendMessageTimeoutW") + if procSendMessageTimeout != nil { + procSendMessageTimeout.Call( + 0xFFFF, // HWND_BROADCAST + 0x001A, // WM_SETTINGCHANGE + uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr("Proxy"))), + 0, + 0x0002, // SMTO_ABORTIFHUNG + 5000, // timeout + ) + } + } } func main() {