sqlite diag

This commit is contained in:
ed 2022-07-16 20:43:26 +02:00
parent a11c1005a8
commit 3fa377a580
6 changed files with 86 additions and 9 deletions

View file

@ -1238,11 +1238,15 @@ if you want thumbnails, `apt -y install ffmpeg`
ideas for context to include in bug reports ideas for context to include in bug reports
in general, commandline arguments (and config file if any)
if something broke during an upload (replacing FILENAME with a part of the filename that broke): if something broke during an upload (replacing FILENAME with a part of the filename that broke):
``` ```
journalctl -aS '48 hour ago' -u copyparty | grep -C10 FILENAME | tee bug.log journalctl -aS '48 hour ago' -u copyparty | grep -C10 FILENAME | tee bug.log
``` ```
if there's a wall of base64 in the log (thread stacks) then please include that, especially if you run into something freezing up or getting stuck, for example `OperationalError('database is locked')` -- alternatively you can visit `/?stack` to see the stacks live, so http://127.0.0.1:3923/?stack for example
# building # building

View file

@ -1107,6 +1107,7 @@ class AuthSrv(object):
vfs.bubble_flags() vfs.bubble_flags()
e2vs = []
t = "volumes and permissions:\n" t = "volumes and permissions:\n"
for zv in vfs.all_vols.values(): for zv in vfs.all_vols.values():
if not self.warn_anonwrite: if not self.warn_anonwrite:
@ -1124,8 +1125,16 @@ class AuthSrv(object):
u = ", ".join("\033[35meverybody\033[0m" if x == "*" else x for x in u) u = ", ".join("\033[35meverybody\033[0m" if x == "*" else x for x in u)
u = u if u else "\033[36m--none--\033[0m" u = u if u else "\033[36m--none--\033[0m"
t += "\n| {}: {}".format(txt, u) t += "\n| {}: {}".format(txt, u)
if "e2v" in zv.flags and zv.axs.uwrite:
e2vs.append(zv.vpath or "/")
t += "\n" t += "\n"
if e2vs:
t += "\n\033[33me2v enabled for the following volumes;\nuploads will be blocked until scan has finished:\n \033[0m"
t += " ".join(e2vs) + "\n"
if self.warn_anonwrite and not self.args.no_voldump: if self.warn_anonwrite and not self.args.no_voldump:
self.log(t) self.log(t)
@ -1133,7 +1142,7 @@ class AuthSrv(object):
zv, _ = vfs.get("/", "*", False, True) zv, _ = vfs.get("/", "*", False, True)
if self.warn_anonwrite and os.getcwd() == zv.realpath: if self.warn_anonwrite and os.getcwd() == zv.realpath:
self.warn_anonwrite = False self.warn_anonwrite = False
t = "anyone can read/write the current directory: {}\n" t = "anyone can write to the current directory: {}\n"
self.log(t.format(zv.realpath), c=1) self.log(t.format(zv.realpath), c=1)
except Pebkac: except Pebkac:
self.warn_anonwrite = True self.warn_anonwrite = True

View file

@ -380,13 +380,18 @@ class HttpCli(object):
if not self._check_nonfatal(pex, post): if not self._check_nonfatal(pex, post):
self.keepalive = False self.keepalive = False
msg = str(ex) if pex == ex else min_ex() em = str(ex)
msg = em if pex == ex else min_ex()
self.log("{}\033[0m, {}".format(msg, self.vpath), 3) self.log("{}\033[0m, {}".format(msg, self.vpath), 3)
msg = "{}\r\nURL: {}\r\n".format(str(ex), self.vpath) msg = "{}\r\nURL: {}\r\n".format(em, self.vpath)
if self.hint: if self.hint:
msg += "hint: {}\r\n".format(self.hint) msg += "hint: {}\r\n".format(self.hint)
if "database is locked" in em:
self.conn.hsrv.broker.say("log_stacks")
msg += "hint: important info in the server log\r\n"
msg = "<pre>" + html_escape(msg) msg = "<pre>" + html_escape(msg)
self.reply(msg.encode("utf-8", "replace"), status=pex.code, volsan=True) self.reply(msg.encode("utf-8", "replace"), status=pex.code, volsan=True)
return self.keepalive return self.keepalive

View file

@ -2,7 +2,9 @@
from __future__ import print_function, unicode_literals from __future__ import print_function, unicode_literals
import argparse import argparse
import base64
import calendar import calendar
import gzip
import os import os
import shlex import shlex
import signal import signal
@ -27,7 +29,7 @@ from .mtag import HAVE_FFMPEG, HAVE_FFPROBE
from .tcpsrv import TcpSrv from .tcpsrv import TcpSrv
from .th_srv import HAVE_PIL, HAVE_VIPS, HAVE_WEBP, ThumbSrv from .th_srv import HAVE_PIL, HAVE_VIPS, HAVE_WEBP, ThumbSrv
from .up2k import Up2k from .up2k import Up2k
from .util import ansi_re, min_ex, mp, start_log_thrs, start_stackmon from .util import ansi_re, min_ex, mp, start_log_thrs, start_stackmon, alltrace
class SvcHub(object): class SvcHub(object):
@ -56,6 +58,7 @@ class SvcHub(object):
self.log_mutex = threading.Lock() self.log_mutex = threading.Lock()
self.next_day = 0 self.next_day = 0
self.tstack = 0.0
if args.sss or args.s >= 3: if args.sss or args.s >= 3:
args.ss = True args.ss = True
@ -500,3 +503,15 @@ class SvcHub(object):
sck.sendall(b"READY=1") sck.sendall(b"READY=1")
except: except:
self.log("sd_notify", min_ex()) self.log("sd_notify", min_ex())
def log_stacks(self) -> None:
td = time.time() - self.tstack
if td < 300:
self.log("stacks", "cooldown {}".format(td))
return
self.tstack = time.time()
zb = alltrace().encode("utf-8", "replace")
zb = gzip.compress(zb)
zs = base64.b64encode(zb).decode("ascii")
self.log("stacks", zs)

View file

@ -98,6 +98,7 @@ class Up2k(object):
self.gid = 0 self.gid = 0
self.stop = False self.stop = False
self.mutex = threading.Lock() self.mutex = threading.Lock()
self.blocked: Optional[str] = None
self.pp: Optional[ProgressPrinter] = None self.pp: Optional[ProgressPrinter] = None
self.rescan_cond = threading.Condition() self.rescan_cond = threading.Condition()
self.need_rescan: set[str] = set() self.need_rescan: set[str] = set()
@ -193,6 +194,14 @@ class Up2k(object):
def log(self, msg: str, c: Union[int, str] = 0) -> None: def log(self, msg: str, c: Union[int, str] = 0) -> None:
self.log_func("up2k", msg + "\033[K", c) self.log_func("up2k", msg + "\033[K", c)
def _block(self, why: str) -> None:
self.blocked = why
self.log("uploads are temporarily blocked due to " + why, 3)
def _unblock(self) -> None:
self.blocked = None
self.log("uploads are now possible", 2)
def get_state(self) -> str: def get_state(self) -> str:
mtpq: Union[int, str] = 0 mtpq: Union[int, str] = 0
q = "select count(w) from mt where k = 't:mtp'" q = "select count(w) from mt where k = 't:mtp'"
@ -416,6 +425,9 @@ class Up2k(object):
self.mtag = None self.mtag = None
# e2ds(a) volumes first # e2ds(a) volumes first
if next((zv for zv in vols if "e2ds" in zv.flags), None):
self._block("indexing")
for vol in vols: for vol in vols:
if self.stop: if self.stop:
break break
@ -445,6 +457,9 @@ class Up2k(object):
self.volstate[vol.vpath] = t self.volstate[vol.vpath] = t
# file contents verification # file contents verification
if next((zv for zv in vols if "e2v" in zv.flags), None):
self._block("integrity verification")
for vol in vols: for vol in vols:
if self.stop: if self.stop:
break break
@ -468,6 +483,9 @@ class Up2k(object):
self.volstate[vol.vpath] = t self.volstate[vol.vpath] = t
if self.blocked:
self._unblock()
# open the rest + do any e2ts(a) # open the rest + do any e2ts(a)
needed_mutagen = False needed_mutagen = False
for vol in vols: for vol in vols:
@ -1485,11 +1503,24 @@ class Up2k(object):
cur.connection.commit() cur.connection.commit()
def _job_volchk(self, cj: dict[str, Any]) -> None:
if not self.register_vpath(cj["ptop"], cj["vcfg"]):
if cj["ptop"] not in self.registry:
raise Pebkac(410, "location unavailable")
def handle_json(self, cj: dict[str, Any]) -> dict[str, Any]: def handle_json(self, cj: dict[str, Any]) -> dict[str, Any]:
with self.mutex: try:
if not self.register_vpath(cj["ptop"], cj["vcfg"]): # bit expensive; 3.9=10x 3.11=2x
if cj["ptop"] not in self.registry: if self.mutex.acquire(timeout=10):
raise Pebkac(410, "location unavailable") self._job_volchk(cj)
self.mutex.release()
else:
t = "cannot receive uploads right now;\nserver busy with {}.\nPlease wait; the client will retry..."
raise Pebkac(503, t.format(self.blocked or "[unknown]"))
except TypeError:
# py2
with self.mutex:
self._job_volchk(cj)
cj["name"] = sanitize_fn(cj["name"], "", [".prologue.html", ".epilogue.html"]) cj["name"] = sanitize_fn(cj["name"], "", [".prologue.html", ".epilogue.html"])
cj["poke"] = time.time() cj["poke"] = time.time()

View file

@ -2244,6 +2244,7 @@ html.y #bbox-overlay figcaption a {
max-width: none; max-width: none;
} }
#u2tab td { #u2tab td {
word-wrap: break-word;
border: 1px solid rgba(128,128,128,0.8); border: 1px solid rgba(128,128,128,0.8);
border-width: 0 0px 1px 0; border-width: 0 0px 1px 0;
padding: .2em .3em; padding: .2em .3em;
@ -2258,7 +2259,19 @@ html.y #bbox-overlay figcaption a {
#u2tab.up.ok td:nth-child(3), #u2tab.up.ok td:nth-child(3),
#u2tab.up.bz td:nth-child(3), #u2tab.up.bz td:nth-child(3),
#u2tab.up.q td:nth-child(3) { #u2tab.up.q td:nth-child(3) {
width: 19em; width: 18em;
}
@media (max-width: 65em) {
#u2tab {
font-size: .9em;
}
}
@media (max-width: 50em) {
#u2tab.up.ok td:nth-child(3),
#u2tab.up.bz td:nth-child(3),
#u2tab.up.q td:nth-child(3) {
width: 16em;
}
} }
#op_up2k.srch td.prog { #op_up2k.srch td.prog {
font-family: sans-serif; font-family: sans-serif;