Skip to content

Commit

Permalink
Fix wrapper related issues on startup and shutdown
Browse files Browse the repository at this point in the history
  • Loading branch information
theotherp committed Apr 1, 2024
1 parent ecf7a31 commit 55fecf7
Show file tree
Hide file tree
Showing 14 changed files with 87 additions and 23 deletions.
2 changes: 1 addition & 1 deletion .idea/misc.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions core/pom.xml
Expand Up @@ -532,6 +532,7 @@
<buildArg>-H:+StaticExecutableWithDynamicLibC</buildArg>
<buildArg>-march=compatibility</buildArg>
<buildArg>--no-fallback -J-Xmx13g</buildArg>
<buildArg>--native-image-info</buildArg>
</buildArgs>
<classesDirectory>${project.build.outputDirectory}</classesDirectory>
<metadataRepository>
Expand Down
1 change: 1 addition & 0 deletions core/src/main/java/org/nzbhydra/NzbHydra.java
Expand Up @@ -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();
Expand Down
12 changes: 7 additions & 5 deletions core/src/main/java/org/nzbhydra/misc/BrowserOpener.java
Expand Up @@ -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
Expand All @@ -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);
}
}

Expand Down
6 changes: 6 additions & 0 deletions core/src/main/resources/changelog.yaml
Expand Up @@ -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"
Expand Down
8 changes: 7 additions & 1 deletion core/src/main/resources/wrapperHashes2.json
@@ -1 +1,7 @@
["2e772a1a140820687d5466e27c030d36f82abb54","ecadc9b8264968a2ca53cedb73f00a69b4172315","847cfdc8a7014c660b47c92e3f55b38b2fdc15ac","15508e8047647e5e6c971b7fde5f81a907a9b358","709e66a3c3267f0ebdf6b37a855de1571037e150"]
[
"2e772a1a140820687d5466e27c030d36f82abb54",
"ecadc9b8264968a2ca53cedb73f00a69b4172315",
"847cfdc8a7014c660b47c92e3f55b38b2fdc15ac",
"15508e8047647e5e6c971b7fde5f81a907a9b358",
"709e66a3c3267f0ebdf6b37a855de1571037e150"
]
2 changes: 1 addition & 1 deletion core/ui-src/html/directives/updates.html
Expand Up @@ -49,7 +49,7 @@
<li>nzbhydra2wrapper.py</li>
<li>nzbhydra2wrapperPy3.py</li>
</ul>
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!
<br><br>
Afterwards start NZBHydra again.
</div>
Expand Down
@@ -1,5 +1,5 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="wrapper native" type="GoApplicationRunConfiguration" factoryName="Go Application">
<configuration default="false" name="wrapper native console" type="GoApplicationRunConfiguration" factoryName="Go Application">
<module name="gowrapper" />
<working_directory value="d:/NZBHydra/nzbhydra2/gowrappertest/native" />
<envs>
Expand Down
4 changes: 4 additions & 0 deletions other/gowrapper/.run/wrapper native gui.run.xml
Expand Up @@ -2,6 +2,10 @@
<configuration default="false" name="wrapper native gui" type="GoApplicationRunConfiguration" factoryName="Go Application">
<module name="gowrapper" />
<working_directory value="d:/NZBHydra/nzbhydra2/gowrappertest/native" />
<envs>
<env name="nzbhydra.devMode" value="true"/>
<env name="nzbhydra_devMode" value="true"/>
</envs>
<kind value="PACKAGE" />
<package value="theotherp/gui" />
<directory value="$PROJECT_DIR$" />
Expand Down
19 changes: 14 additions & 5 deletions other/gowrapper/base/base.go
Expand Up @@ -21,6 +21,7 @@ import (

type ReleaseType string
type ExitFunction func(code int)
type StartupErrorHandler func(message string)

const (
NATIVE ReleaseType = "native"
Expand All @@ -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")
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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 {
Expand Down
9 changes: 7 additions & 2 deletions 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)
}
36 changes: 33 additions & 3 deletions other/gowrapper/gui/gui.go
Expand Up @@ -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")
Expand All @@ -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
}
Expand All @@ -32,32 +50,44 @@ 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())
}()

menuItemShutdown := systray.AddMenuItem("Shutdown", "")
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)
Expand Down
4 changes: 2 additions & 2 deletions releases/windows-release/include/NZBHydra2 Console.exe
Git LFS file not shown
4 changes: 2 additions & 2 deletions releases/windows-release/include/NZBHydra2.exe
Git LFS file not shown

0 comments on commit 55fecf7

Please sign in to comment.