mirror of
https://github.com/9001/copyparty.git
synced 2025-08-17 09:02:15 -06:00
ensure OS signals hit main-thread as intended;
use sigmasks to block SIGINT, SIGTERM, SIGUSR1 from all other threads also initiate shutdown by calling sighandler directly, in case this misses anything and that is still unreliable (discovered by `--exit=idx` being noop once in a blue moon)
This commit is contained in:
parent
2c92dab165
commit
87c60a1ec9
19
bin/u2c.py
19
bin/u2c.py
|
@ -1,8 +1,8 @@
|
|||
#!/usr/bin/env python3
|
||||
from __future__ import print_function, unicode_literals
|
||||
|
||||
S_VERSION = "1.16"
|
||||
S_BUILD_DT = "2024-04-20"
|
||||
S_VERSION = "1.17"
|
||||
S_BUILD_DT = "2024-05-09"
|
||||
|
||||
"""
|
||||
u2c.py: upload to copyparty
|
||||
|
@ -79,12 +79,21 @@ req_ses = requests.Session()
|
|||
|
||||
|
||||
class Daemon(threading.Thread):
|
||||
def __init__(self, target, name=None, a=None):
|
||||
# type: (Any, Any, Any) -> None
|
||||
threading.Thread.__init__(self, target=target, args=a or (), name=name)
|
||||
def __init__(self, target, name = None, a = None):
|
||||
threading.Thread.__init__(self, name=name)
|
||||
self.a = a or ()
|
||||
self.fun = target
|
||||
self.daemon = True
|
||||
self.start()
|
||||
|
||||
def run(self):
|
||||
try:
|
||||
signal.pthread_sigmask(signal.SIG_BLOCK, [signal.SIGINT, signal.SIGTERM])
|
||||
except:
|
||||
pass
|
||||
|
||||
self.fun(*self.a)
|
||||
|
||||
|
||||
class File(object):
|
||||
"""an up2k upload task; represents a single file"""
|
||||
|
|
|
@ -49,6 +49,7 @@ from .util import (
|
|||
PYFTPD_VER,
|
||||
SQLITE_VER,
|
||||
UNPLICATIONS,
|
||||
Daemon,
|
||||
align_tab,
|
||||
ansi_re,
|
||||
dedent,
|
||||
|
@ -471,6 +472,16 @@ def disable_quickedit() -> None:
|
|||
cmode(True, mode | 4)
|
||||
|
||||
|
||||
def sfx_tpoke(top: str):
|
||||
files = [os.path.join(dp, p) for dp, dd, df in os.walk(top) for p in dd + df]
|
||||
while True:
|
||||
t = int(time.time())
|
||||
for f in [top] + files:
|
||||
os.utime(f, (t, t))
|
||||
|
||||
time.sleep(78123)
|
||||
|
||||
|
||||
def showlic() -> None:
|
||||
p = os.path.join(E.mod, "res", "COPYING.txt")
|
||||
if not os.path.exists(p):
|
||||
|
@ -1454,6 +1465,12 @@ def main(argv: Optional[list[str]] = None, rsrc: Optional[str] = None) -> None:
|
|||
if EXE:
|
||||
print("pybin: {}\n".format(pybin), end="")
|
||||
|
||||
for n, zs in enumerate(argv):
|
||||
if zs.startswith("--sfx-tpoke="):
|
||||
Daemon(sfx_tpoke, "sfx-tpoke", (zs.split("=", 1)[1],))
|
||||
argv.pop(n)
|
||||
break
|
||||
|
||||
ensure_locale()
|
||||
|
||||
ensure_webdeps()
|
||||
|
|
|
@ -57,11 +57,8 @@ class BrokerMp(object):
|
|||
def shutdown(self) -> None:
|
||||
self.log("broker", "shutting down")
|
||||
for n, proc in enumerate(self.procs):
|
||||
thr = threading.Thread(
|
||||
target=proc.q_pend.put((0, "shutdown", [])),
|
||||
name="mp-shutdown-{}-{}".format(n, len(self.procs)),
|
||||
)
|
||||
thr.start()
|
||||
name = "mp-shut-%d-%d" % (n, len(self.procs))
|
||||
Daemon(proc.q_pend.put, name, ((0, "shutdown", []),))
|
||||
|
||||
with self.mutex:
|
||||
procs = self.procs
|
||||
|
|
|
@ -266,10 +266,7 @@ class HttpSrv(object):
|
|||
msg = "subscribed @ {}:{} f{} p{}".format(hip, port, fno, os.getpid())
|
||||
self.log(self.name, msg)
|
||||
|
||||
def fun() -> None:
|
||||
self.broker.say("cb_httpsrv_up")
|
||||
|
||||
threading.Thread(target=fun, name="sig-hsrv-up1").start()
|
||||
Daemon(self.broker.say, "sig-hsrv-up1", ("cb_httpsrv_up",))
|
||||
|
||||
while not self.stopping:
|
||||
if self.args.log_conn:
|
||||
|
|
|
@ -127,7 +127,7 @@ class SMB(object):
|
|||
self.log("smb", msg, c)
|
||||
|
||||
def start(self) -> None:
|
||||
Daemon(self.srv.start)
|
||||
Daemon(self.srv.start, "smbd")
|
||||
|
||||
def _auth_cb(self, *a, **ka):
|
||||
debug("auth-result: %s %s", a, ka)
|
||||
|
|
|
@ -293,13 +293,14 @@ class SvcHub(object):
|
|||
from .ftpd import Ftpd
|
||||
|
||||
self.ftpd: Optional[Ftpd] = None
|
||||
Daemon(self.start_ftpd, "start_ftpd")
|
||||
zms += "f" if args.ftp else "F"
|
||||
|
||||
if args.tftp:
|
||||
from .tftpd import Tftpd
|
||||
|
||||
self.tftpd: Optional[Tftpd] = None
|
||||
|
||||
if args.ftp or args.ftps or args.tftp:
|
||||
Daemon(self.start_ftpd, "start_tftpd")
|
||||
|
||||
if args.smb:
|
||||
|
@ -388,7 +389,7 @@ class SvcHub(object):
|
|||
self.sigterm()
|
||||
|
||||
def sigterm(self) -> None:
|
||||
os.kill(os.getpid(), signal.SIGTERM)
|
||||
self.signal_handler(signal.SIGTERM, None)
|
||||
|
||||
def cb_httpsrv_up(self) -> None:
|
||||
self.httpsrv_up += 1
|
||||
|
|
|
@ -10,7 +10,6 @@ import math
|
|||
import os
|
||||
import re
|
||||
import shutil
|
||||
import signal
|
||||
import stat
|
||||
import subprocess as sp
|
||||
import tempfile
|
||||
|
@ -1659,7 +1658,7 @@ class Up2k(object):
|
|||
|
||||
if e2vp and rewark:
|
||||
self.hub.retcode = 1
|
||||
os.kill(os.getpid(), signal.SIGTERM)
|
||||
Daemon(self.hub.sigterm)
|
||||
raise Exception("{} files have incorrect hashes".format(len(rewark)))
|
||||
|
||||
if not e2vu or not rewark:
|
||||
|
|
|
@ -463,13 +463,20 @@ class Daemon(threading.Thread):
|
|||
r: bool = True,
|
||||
ka: Optional[dict[Any, Any]] = None,
|
||||
) -> None:
|
||||
threading.Thread.__init__(
|
||||
self, target=target, name=name, args=a or (), kwargs=ka
|
||||
)
|
||||
threading.Thread.__init__(self, name=name)
|
||||
self.a = a or ()
|
||||
self.ka = ka or {}
|
||||
self.fun = target
|
||||
self.daemon = True
|
||||
if r:
|
||||
self.start()
|
||||
|
||||
def run(self):
|
||||
if not ANYWIN and not PY2:
|
||||
signal.pthread_sigmask(signal.SIG_BLOCK, [signal.SIGINT, signal.SIGTERM, signal.SIGUSR1])
|
||||
|
||||
self.fun(*self.a, **self.ka)
|
||||
|
||||
|
||||
class Netdev(object):
|
||||
def __init__(self, ip: str, idx: int, name: str, desc: str):
|
||||
|
@ -864,6 +871,7 @@ class ProgressPrinter(threading.Thread):
|
|||
self.start()
|
||||
|
||||
def run(self) -> None:
|
||||
sigblock()
|
||||
tp = 0
|
||||
msg = None
|
||||
no_stdout = self.args.q
|
||||
|
@ -1308,6 +1316,13 @@ def log_thrs(log: Callable[[str, str, int], None], ival: float, name: str) -> No
|
|||
log(name, "\033[0m \033[33m".join(tv), 3)
|
||||
|
||||
|
||||
def sigblock():
|
||||
if ANYWIN or PY2:
|
||||
return
|
||||
|
||||
signal.pthread_sigmask(signal.SIG_BLOCK, [signal.SIGINT, signal.SIGTERM, signal.SIGUSR1])
|
||||
|
||||
|
||||
def vol_san(vols: list["VFS"], txt: bytes) -> bytes:
|
||||
txt0 = txt
|
||||
for vol in vols:
|
||||
|
@ -1329,9 +1344,10 @@ def vol_san(vols: list["VFS"], txt: bytes) -> bytes:
|
|||
|
||||
def min_ex(max_lines: int = 8, reverse: bool = False) -> str:
|
||||
et, ev, tb = sys.exc_info()
|
||||
stb = traceback.extract_tb(tb)
|
||||
stb = traceback.extract_tb(tb) if tb else traceback.extract_stack()[:-1]
|
||||
fmt = "%s @ %d <%s>: %s"
|
||||
ex = [fmt % (fp.split(os.sep)[-1], ln, fun, txt) for fp, ln, fun, txt in stb]
|
||||
if et or ev or tb:
|
||||
ex.append("[%s] %s" % (et.__name__ if et else "(anonymous)", ev))
|
||||
return "\n".join(ex[-max_lines:][:: -1 if reverse else 1])
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
#!/usr/bin/env python3
|
||||
# coding: latin-1
|
||||
from __future__ import print_function, unicode_literals
|
||||
import re, os, sys, time, shutil, signal, threading, tarfile, hashlib, platform, tempfile, traceback
|
||||
import re, os, sys, time, shutil, signal, tarfile, hashlib, platform, tempfile, traceback
|
||||
import subprocess as sp
|
||||
|
||||
|
||||
|
@ -368,17 +368,6 @@ def get_payload():
|
|||
p = a
|
||||
|
||||
|
||||
def utime(top):
|
||||
# avoid cleaners
|
||||
files = [os.path.join(dp, p) for dp, dd, df in os.walk(top) for p in dd + df]
|
||||
while True:
|
||||
t = int(time.time())
|
||||
for f in [top] + files:
|
||||
os.utime(f, (t, t))
|
||||
|
||||
time.sleep(78123)
|
||||
|
||||
|
||||
def confirm(rv):
|
||||
msg()
|
||||
msg("retcode", rv if rv else traceback.format_exc())
|
||||
|
@ -398,9 +387,7 @@ def run(tmp, j2, ftp):
|
|||
msg("sfxdir:", tmp)
|
||||
msg()
|
||||
|
||||
t = threading.Thread(target=utime, args=(tmp,), name="utime")
|
||||
t.daemon = True
|
||||
t.start()
|
||||
sys.argv.append("--sfx-tpoke=" + tmp)
|
||||
|
||||
ld = (("", ""), (j2, "j2"), (ftp, "ftp"), (not PY2, "py2"), (PY37, "py37"))
|
||||
ld = [os.path.join(tmp, b) for a, b in ld if not a]
|
||||
|
|
|
@ -6,7 +6,6 @@ import platform
|
|||
import sys
|
||||
import tarfile
|
||||
import tempfile
|
||||
import threading
|
||||
import time
|
||||
import traceback
|
||||
|
||||
|
@ -80,9 +79,7 @@ def run():
|
|||
msg(" rsrc dir:", rsrc)
|
||||
msg()
|
||||
|
||||
t = threading.Thread(target=utime, args=(rsrc,), name="utime")
|
||||
t.daemon = True
|
||||
t.start()
|
||||
sys.argv.append("--sfx-tpoke=" + rsrc)
|
||||
|
||||
cm(rsrc=rsrc)
|
||||
|
||||
|
|
Loading…
Reference in a new issue