diff --git a/.idea/misc.xml b/.idea/misc.xml index d1afd7c27..b85a2a86f 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -70,7 +70,7 @@ - + \ No newline at end of file diff --git a/core/pom.xml b/core/pom.xml index 0c75803f9..fafb9528c 100644 --- a/core/pom.xml +++ b/core/pom.xml @@ -532,6 +532,7 @@ -H:+StaticExecutableWithDynamicLibC -march=compatibility --no-fallback -J-Xmx13g + --native-image-info ${project.build.outputDirectory} diff --git a/core/src/main/java/org/nzbhydra/NzbHydra.java b/core/src/main/java/org/nzbhydra/NzbHydra.java index 5de81d6bc..e0595cd10 100644 --- a/core/src/main/java/org/nzbhydra/NzbHydra.java +++ b/core/src/main/java/org/nzbhydra/NzbHydra.java @@ -329,6 +329,7 @@ public void startupDone(ApplicationReadyEvent event) { logger.info("Not opening browser after restart"); return; } + logger.debug("Opening browser"); browserOpener.openBrowser(); } URI uri = urlCalculator.getLocalBaseUriBuilder().build().toUri(); diff --git a/core/src/main/java/org/nzbhydra/misc/BrowserOpener.java b/core/src/main/java/org/nzbhydra/misc/BrowserOpener.java index 303b8df24..9489f3606 100644 --- a/core/src/main/java/org/nzbhydra/misc/BrowserOpener.java +++ b/core/src/main/java/org/nzbhydra/misc/BrowserOpener.java @@ -6,7 +6,7 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; -import java.awt.*; +import java.awt.Desktop; import java.net.URI; @Component @@ -19,22 +19,24 @@ public class BrowserOpener { public void openBrowser() { Desktop desktop; + URI uri = urlCalculator.getLocalBaseUriBuilder().build().toUri(); try { desktop = Desktop.isDesktopSupported() ? Desktop.getDesktop() : null; + logger.debug("Desktop supported: {}", Desktop.isDesktopSupported()); } catch (Throwable e) { - logger.debug("Unable to get desktop"); + logger.debug("Unable to get desktop", e); + logger.error("Unable to open browser. Go to {}", uri, e); return; } - URI uri = urlCalculator.getLocalBaseUriBuilder().build().toUri(); if (desktop != null && desktop.isSupported(Desktop.Action.BROWSE)) { logger.info("Opening {} in browser", uri); try { desktop.browse(uri); } catch (Exception e) { - logger.error("Unable to open browser. Go to " + uri.toString(), e); + logger.error("Unable to open browser. Go to {}", uri, e); } } else { - logger.error("Unable to open browser. Go to " + uri.toString()); + logger.error("Unable to open browser. Go to {}", uri); } } diff --git a/core/src/main/resources/changelog.yaml b/core/src/main/resources/changelog.yaml index f62869fd3..d94fbf97c 100644 --- a/core/src/main/resources/changelog.yaml +++ b/core/src/main/resources/changelog.yaml @@ -5,6 +5,12 @@ text: "I've completely rewritten the wrapper for windows. It's not a packaged python script anymore but an actually compiled binary. This has a couple of benefits: No more false positives from virus scanners (VirusTotal shows 5/72). No more temporary files not being cleaned up after a crash. The files are (a bit) smaller.\nI don't plan to compile the wrapper for anything but windows as it makes more sense and is easier to run the python wrapper instead." - type: "fix" text: "IPs or usernames were not shown in the history. See #932" + - type: "fix" + text: "Removed annoying and misleading warning regarding memory leaks when shutting down process." + - type: "fix" + text: "Improved logging of outdated wrappers." + - type: "fix" + text: "Properly remove system tray icon after shutdown" final: true - version: "v5.3.11" date: "2024-03-23" diff --git a/core/src/main/resources/wrapperHashes2.json b/core/src/main/resources/wrapperHashes2.json index 28ea155b6..fa1751ec3 100644 --- a/core/src/main/resources/wrapperHashes2.json +++ b/core/src/main/resources/wrapperHashes2.json @@ -1 +1,7 @@ -["2e772a1a140820687d5466e27c030d36f82abb54","ecadc9b8264968a2ca53cedb73f00a69b4172315","847cfdc8a7014c660b47c92e3f55b38b2fdc15ac","15508e8047647e5e6c971b7fde5f81a907a9b358","709e66a3c3267f0ebdf6b37a855de1571037e150"] \ No newline at end of file +[ + "2e772a1a140820687d5466e27c030d36f82abb54", + "ecadc9b8264968a2ca53cedb73f00a69b4172315", + "847cfdc8a7014c660b47c92e3f55b38b2fdc15ac", + "15508e8047647e5e6c971b7fde5f81a907a9b358", + "709e66a3c3267f0ebdf6b37a855de1571037e150" +] \ No newline at end of file diff --git a/core/ui-src/html/directives/updates.html b/core/ui-src/html/directives/updates.html index f4ab57631..0da941fc0 100644 --- a/core/ui-src/html/directives/updates.html +++ b/core/ui-src/html/directives/updates.html @@ -49,7 +49,7 @@
  • nzbhydra2wrapper.py
  • nzbhydra2wrapperPy3.py
  • - Make sure to overwrite all of these files that already exist - you don't need to update any files that aren't already present. If you added python scripts manually make sure to update them as well! + Make sure to overwrite all of these files that already exist - you don't need to update any files that aren't already present. If you added any of the other listed files manually make sure to update them as well!

    Afterwards start NZBHydra again. diff --git a/other/gowrapper/.run/wrapper native.run.xml b/other/gowrapper/.run/wrapper native console.run.xml similarity index 76% rename from other/gowrapper/.run/wrapper native.run.xml rename to other/gowrapper/.run/wrapper native console.run.xml index 06b50023f..59a90323e 100644 --- a/other/gowrapper/.run/wrapper native.run.xml +++ b/other/gowrapper/.run/wrapper native console.run.xml @@ -1,5 +1,5 @@ - + diff --git a/other/gowrapper/.run/wrapper native gui.run.xml b/other/gowrapper/.run/wrapper native gui.run.xml index 649b59ec5..71c4ad26c 100644 --- a/other/gowrapper/.run/wrapper native gui.run.xml +++ b/other/gowrapper/.run/wrapper native gui.run.xml @@ -2,6 +2,10 @@ + + + + diff --git a/other/gowrapper/base/base.go b/other/gowrapper/base/base.go index 8dd3e63c3..d3a062d4c 100644 --- a/other/gowrapper/base/base.go +++ b/other/gowrapper/base/base.go @@ -21,6 +21,7 @@ import ( type ReleaseType string type ExitFunction func(code int) +type StartupErrorHandler func(message string) const ( NATIVE ReleaseType = "native" @@ -40,6 +41,7 @@ var hideWindow = false var Uri = "" var consoleLines []string var Exit = os.Exit +var startupErrorHandler StartupErrorHandler var ( argsJavaExecutable = flag.String("java", "java", "Full path to java executable") @@ -343,15 +345,15 @@ func determineXmxAndLogGc() (string, bool) { } func handleUnexpectedExit() { - message := "Main process shut down unexpectedly." + message := "NZBHydra main process shut down unexpectedly." for _, x := range consoleLines { if strings.Contains(x, "Unrecognized option: -Xlog") { - message = "You seem to be trying to run NZBHydra with a wrong Java version. Please make sure to use at least Java 9" + message = "You seem to be trying to run NZBHydra with a wrong Java version. Please make sure to use at least Java 17." } else if strings.Contains(x, "java.lang.OutOfMemoryError") { - message = "The main process has exited because it didn't have enough memory. Please increase the XMX value in the main config" + message = "The NZBHydra main process has exited because it didn't have enough memory. Please increase the XMX value in the main config." } } - LogFile(logrus.ErrorLevel, message) + startupErrorHandler(message) LogFile(logrus.ErrorLevel, "The last 250 lines from output:") for _, line := range consoleLines { LogFile(logrus.ErrorLevel, line) @@ -554,14 +556,20 @@ func checkLogLine(line string) { markerLine = "Unable to open browser. Go to" if strings.Contains(line, markerLine) { urlToOpen := strings.TrimSpace(line[strings.Index(line, markerLine)+len(markerLine):]) + Log(logrus.InfoLevel, "Main process was unable to open browser. Will try here to open "+urlToOpen) OpenBrowser(urlToOpen) } + markerLine = "PortInUseException" + if strings.Contains(line, markerLine) { + startupErrorHandler("The port configured for NZBHydra is already in use. Please check the port configuration in the settings.") + } if strings.Contains(line, "Started NzbHydra in") { Log(logrus.InfoLevel, "Main process has started successfully") } } func OpenBrowser(urlToOpen string) { + Logf(logrus.InfoLevel, "Opening URL %s", urlToOpen) err := exec.Command("rundll32", "url.dll,FileProtocolHandler", urlToOpen).Start() if err != nil { Log(logrus.ErrorLevel, "Unable to open browser", err) @@ -629,8 +637,9 @@ func executeWaitingForSignal(function Function) { <-done } -func Entrypoint(_hideWindow bool, waitForSignal bool) { +func Entrypoint(_hideWindow bool, waitForSignal bool, _errorHandler StartupErrorHandler) { hideWindow = _hideWindow + startupErrorHandler = _errorHandler if waitForSignal { executeWaitingForSignal(_main) } else { diff --git a/other/gowrapper/console/console.go b/other/gowrapper/console/console.go index 3e2732c4e..17eb9e926 100644 --- a/other/gowrapper/console/console.go +++ b/other/gowrapper/console/console.go @@ -1,9 +1,14 @@ package main import ( - "theotherp/base" + "github.com/sirupsen/logrus" + "theotherp/base" ) +func StartupErrorHandler(message string) { + base.Logf(logrus.ErrorLevel, message) +} + func main() { - base.Entrypoint(false, true) + base.Entrypoint(false, true, StartupErrorHandler) } diff --git a/other/gowrapper/gui/gui.go b/other/gowrapper/gui/gui.go index a33496d93..04cd14851 100644 --- a/other/gowrapper/gui/gui.go +++ b/other/gowrapper/gui/gui.go @@ -3,17 +3,34 @@ package main import ( "encoding/base64" "github.com/getlantern/systray" + "github.com/sirupsen/logrus" "os" "tawesoft.co.uk/go/dialog" "theotherp/base" + "time" ) const IcoBytesB64 = "AAABAAEAEBAAAAEAIABoBAAAFgAAACgAAAAQAAAAIAAAAAEAIAAAAAAAAAQAACMuAAAjLgAAAAAAAAAAAAAAAAD8DxMO/i05J/4sOyL+NVAf/kZxH/5VjyP+WJwg/0iJEf4zYwn+FygK/gEBAf4AAAD+AAAA/gAAAP4AAAD8AAAA/gICAv8gKBz/Qlc1/0RfMP82SyT/LUAd/zJLH/9DbST/R44P/1CaFP8qQxj/AAAB/wAAAP8AAAD/AAAA/gAAAP4AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/BAUD/yM/Dv9NnQn/Z6cy/xciD/8AAAD/AAAA/wAAAP4AAAD+AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8KDwb/RIwE/3C7MP85UyX/AAAA/wAAAP8AAAD+AAAA/gAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8GCQX/KksM/1CkAv9xuzH/QV0r/wAAAP8AAAD/AAEA/gAAAP4AAAD/AAAA/wAAAP8AAAD/AAAA/wIDAv8qPSH/Wo03/220Mv9gsBj/ebw+/y9CIP8AAAD/AAAA/wAAAP4AAAD+AAAA/wAAAP8AAAD/AAAA/wAAAP84STL/jbx4/4m6bv9dgkT/XJgr/3yyTv8THA3/AAAA/wAAAP8AAAD+AAAA/gAAAP8ICQn/QUVB/xkaGf8RFBD/i6qB/5e8if+Lqn3/OEwv/3u1Uv9egET/AQIB/wAAAP8AAAD/AAAA/gABAP4AAAD/ERMR/5qnl/+erJr/j6GK/6bAnv+cv5D/fJF0/zdMLf+NwHH/Kzkj/wAAAP8AAAD/AAAA/wAAAP4AAQD+AAAA/wAAAP88QDv/k5+P/4iThf81OjP/k6yL/2Z1Yv82SDD/hat0/w4RDf8AAAD/AAAA/wAAAP8AAAD+AAAA/gAAAP8AAAD/AAAA/wsLC/9cYlv/Ghsa/4CQfP9gal3/ISoe/46ygP8sNij/HCYX/xkkFP8CAwL/AAEA/gAAAP4AAAD/AAAA/wAAAP8SExL/n62b/11lXP+XpJP/WF5W/wcIB/93k27/j7l//3upaP9WekX/DBEK/wAAAP4AAAD+AAAA/wAAAP8AAAD/CAgI/36Je/+1x7D/pbOh/yQlI/8DAwP/eo91/3CGaf9DWDz/Hyka/wECAf8AAAD+AAAA/gAAAP8AAAD/AAAA/wAAAP8NDg3/LTEs/xkbGf8AAAD/BwgH/5SlkP9BR0D/AAAA/wAAAP8AAAD/AAAA/gAAAP4AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wMDA/+Cjn//hZKB/0lQRv8JCQn/AAAA/wAAAP4AAAD8AAAA/gAAAP4AAAD+AAAA/gAAAP4AAAD+AAAA/gAAAP4AAAD+Ky8q/o6bi/5xfG3+CgoK/gAAAP4AAAD8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==" +var shownAlerts = []string{} + func main() { + base.Exit = exit systray.Run(onReady, onExit) } +func StartupErrorHandler(message string) { + base.Logf(logrus.ErrorLevel, message) + //The PortAlreadyInUseException is logged twice, but we want to show the message only once + for _, shownMessage := range shownAlerts { + if shownMessage == message { + return + } + } + dialog.Alert(message) + shownAlerts = append(shownAlerts, message) +} + func onReady() { systray.SetIcon(getIcon()) systray.SetTitle("NZBHydra2") @@ -22,6 +39,7 @@ func onReady() { go func() { <-menuItemOpenWebUI.ClickedCh if base.Uri == "" { + base.Logf(logrus.ErrorLevel, "NZBHydra2 URI could not be determined") dialog.Alert("NZBHydra2 URI could not be determined") return } @@ -32,9 +50,11 @@ func onReady() { go func() { <-menuItemRestart.ClickedCh if base.Uri == "" { + base.Logf(logrus.ErrorLevel, "NZBHydra2 URI could not be determined") dialog.Alert("NZBHydra2 URI could not be determined") return } + base.Logf(logrus.InfoLevel, "Sending restart command to main process") _, _ = base.ExecuteGetRequest(base.Uri + "internalapi/control/restart?internalApiKey=" + base.GetInternalApiKey()) }() @@ -42,22 +62,32 @@ func onReady() { go func() { <-menuItemShutdown.ClickedCh if base.Uri != "" { + base.Logf(logrus.InfoLevel, "Sending shutdown command to main process") resp, _ := base.ExecuteGetRequest(base.Uri + "internalapi/control/shutdown?internalApiKey=" + base.GetInternalApiKey()) if resp.StatusCode != 200 { + base.Logf(logrus.WarnLevel, "Shutdown command could not be sent to main process - shutting down wrapper") //Try shutting down wrapper, child process is hopefully killed gracefully - os.Exit(0) + exit(0) } + base.Logf(logrus.InfoLevel, "Successfully sent shutdown command to main process") return } - os.Exit(0) + base.Logf(logrus.ErrorLevel, "NZBHydra2 URI could not be determined - shutting down wrapper") + exit(0) }() - base.Entrypoint(true, false) + base.Entrypoint(true, false, StartupErrorHandler) } func onExit() { } +func exit(code int) { + systray.Quit() + //Give systray time to quit + time.Sleep(1000 * time.Millisecond) + os.Exit(code) +} func getIcon() []byte { decodedBytes, err := base64.StdEncoding.DecodeString(IcoBytesB64) diff --git a/releases/windows-release/include/NZBHydra2 Console.exe b/releases/windows-release/include/NZBHydra2 Console.exe index 8cd049809..d701e04de 100644 --- a/releases/windows-release/include/NZBHydra2 Console.exe +++ b/releases/windows-release/include/NZBHydra2 Console.exe @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:84da467d610c37b2817c858901c7a16d10c327fd71f62026007df45e5127c5e9 -size 3461632 +oid sha256:f7afbe1d1dd4ee5a2985817e7d7519a5215ac4a80c3de69818a1e213ab07ff67 +size 3458560 diff --git a/releases/windows-release/include/NZBHydra2.exe b/releases/windows-release/include/NZBHydra2.exe index 806114af7..fe382fcf2 100644 --- a/releases/windows-release/include/NZBHydra2.exe +++ b/releases/windows-release/include/NZBHydra2.exe @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a40f39a1b624c150fb47c362099ebda2d0706723f2fa71ada2ede7eb281e0182 -size 5474816 +oid sha256:80a87ee7f8ad9b7497b232d578c7725a845993efe2ff30aada34b94fec69599b +size 5476864