diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx
index c218829..709a816 100755
--- a/frontend/src/App.tsx
+++ b/frontend/src/App.tsx
@@ -163,7 +163,7 @@ function AppContent() {
} />
- } />
+ } />
diff --git a/frontend/src/Settings.tsx b/frontend/src/Settings.tsx
index 6379329..bac849a 100644
--- a/frontend/src/Settings.tsx
+++ b/frontend/src/Settings.tsx
@@ -22,6 +22,7 @@ import { useDispatch, useSelector } from "react-redux";
import { debounceTime, distinctUntilChanged, map, of, takeWhile } from "rxjs";
import { CliArguments } from "./features/core/argsParser";
import I18nBuilder from "./features/core/intl";
+import { RPCClient } from "./features/core/rpcClient";
import {
LanguageUnion,
setCliArgs,
@@ -38,7 +39,7 @@ import { updated } from "./features/status/statusSlice";
import { RootState } from "./stores/store";
import { validateDomain, validateIP } from "./utils";
-export default function Settings() {
+export default function Settings({ socket }: { socket: WebSocket }) {
const settings = useSelector((state: RootState) => state.settings)
const status = useSelector((state: RootState) => state.status)
const dispatch = useDispatch()
@@ -46,6 +47,7 @@ export default function Settings() {
const [invalidIP, setInvalidIP] = useState(false);
const i18n = useMemo(() => new I18nBuilder(settings.language), [settings.language])
+ const client = useMemo(() => new RPCClient(socket), [settings.serverAddr, settings.serverPort])
const cliArgs = useMemo(() => new CliArguments().fromString(settings.cliArgs), [settings.cliArgs])
/**
* Update the server ip address state and localstorage whenever the input value changes.
@@ -107,7 +109,7 @@ export default function Settings() {
* Send via WebSocket a message in order to update the yt-dlp binary from server
*/
const updateBinary = () => {
-
+ client.updateExecutable().then(() => dispatch(updated()))
}
return (
diff --git a/frontend/src/features/core/rpcClient.ts b/frontend/src/features/core/rpcClient.ts
index b693ac7..3ca0363 100644
--- a/frontend/src/features/core/rpcClient.ts
+++ b/frontend/src/features/core/rpcClient.ts
@@ -92,6 +92,13 @@ export class RPCClient {
})
}
+ public updateExecutable() {
+ return this.sendHTTP({
+ method: 'Service.UpdateExecutable',
+ params: []
+ })
+ }
+
public decode(data: any): RPCResponse {
return JSON.parse(data)
}
diff --git a/server/process.go b/server/process.go
index 2f73768..f7cff0b 100644
--- a/server/process.go
+++ b/server/process.go
@@ -4,6 +4,7 @@ import (
"bufio"
"fmt"
"regexp"
+ "syscall"
"github.com/goccy/go-json"
@@ -89,6 +90,8 @@ func (p *Process) Start(path, filename string) {
// ----------------- main block ----------------- //
cmd := exec.Command(cfg.GetConfig().DownloaderPath, params...)
+ cmd.SysProcAttr = &syscall.SysProcAttr{Setpgid: true}
+
r, err := cmd.StdoutPipe()
if err != nil {
log.Panicln(err)
@@ -107,6 +110,8 @@ func (p *Process) Start(path, filename string) {
// spawn a goroutine that retrieves the info for the download
go func() {
cmd := exec.Command(cfg.GetConfig().DownloaderPath, p.url, "-J")
+ cmd.SysProcAttr = &syscall.SysProcAttr{Setpgid: true}
+
stdout, err := cmd.Output()
if err != nil {
log.Println("Cannot retrieve info for", p.url)
@@ -132,8 +137,8 @@ func (p *Process) Start(path, filename string) {
cmd.Wait()
}()
- // do the unmarshal operation every 500ms (consumer)
- go rx.Debounce(time.Millisecond*500, eventChan, func(text string) {
+ // do the unmarshal operation every 250ms (consumer)
+ go rx.Debounce(time.Millisecond*250, eventChan, func(text string) {
stdout := ProgressTemplate{}
err := json.Unmarshal([]byte(text), &stdout)
if err == nil {
@@ -162,7 +167,11 @@ func (p *Process) Complete() {
// Kill a process and remove it from the memory
func (p *Process) Kill() error {
- err := p.proc.Kill()
+ pgid, err := syscall.Getpgid(p.proc.Pid)
+ if err != nil {
+ return err
+ }
+ err = syscall.Kill(-pgid, syscall.SIGTERM)
p.mem.Delete(p.id)
log.Printf("Killed process %s\n", p.id)
return err
diff --git a/server/service.go b/server/service.go
index bdf87ae..62bb73c 100644
--- a/server/service.go
+++ b/server/service.go
@@ -31,7 +31,7 @@ type DownloadSpecificArgs struct {
// Exec spawns a Process.
// The result of the execution is the newly spawned process Id.
func (t *Service) Exec(args DownloadSpecificArgs, result *string) error {
- log.Printf("Spawning new process for %s\n", args.URL)
+ log.Println("Spawning new process for", args.URL)
p := Process{mem: &db, url: args.URL, params: args.Params}
p.Start(args.Path, args.Rename)
*result = p.id
@@ -66,6 +66,7 @@ func (t *Service) Running(args NoArgs, running *Running) error {
// Kill kills a process given its id and remove it from the memoryDB
func (t *Service) Kill(args string, killed *string) error {
+ log.Println("Trying killing process with id", args)
proc := db.Get(args)
var err error
if proc != nil {
@@ -77,6 +78,7 @@ func (t *Service) Kill(args string, killed *string) error {
// KillAll kills all process unconditionally and removes them from
// the memory db
func (t *Service) KillAll(args NoArgs, killed *string) error {
+ log.Println("Killing all spawned processes", args)
keys := db.Keys()
var err error
for _, key := range keys {
@@ -102,6 +104,7 @@ func (t *Service) DirectoryTree(args NoArgs, tree *[]string) error {
}
func (t *Service) UpdateExecutable(args NoArgs, updated *bool) error {
+ log.Println("Updating yt-dlp executable to the latest release")
err := updater.UpdateExecutable()
if err != nil {
*updated = true