mirror of
https://github.com/lucannez64/darling-lol.git
synced 2026-10-26 19:47:42 +00:00
fix(launchd): reap orphaned guest zombies and harden stale-client recovery
Children whose parent dies are reparented to the guest launchd, and its job manager only reaps PIDs it has a job record for, so every leftover mldr/CEF process from a killed client tree stayed a zombie until shutdown. Reap zombies that launchd owns but does not track on a 5 second timer; tracked jobs keep their exit status for job_reap(). proc_listpids() is not implemented in Darling yet, so the scan enumerates the guest PID namespace through /proc. recover-stale-client now signals the stale tree deepest-first so a live parent can still reap its own children, and prepare.py repairs interrupted checkouts and missing Git LFS objects instead of publishing pointer text as a library.
This commit is contained in:
1 parent
24276b91c6
commit
9291d6accd
5 files changed
+233
-20
No files matched your search
Executable → Regular
+35
-2
@@ -7,9 +7,38 @@ sys.dont_write_bytecode=True
|
||||
from common import ROOT,render
|
||||
p=argparse.ArgumentParser(description=__doc__)
|
||||
p.add_argument('--source',type=Path,default=ROOT/'build/darling-src')
|
||||
p.add_argument('--jobs',type=int,default=4,help='parallel submodule fetches')
|
||||
p.add_argument('--check-only',action='store_true',help='validate against temporary base indexes, without changing existing source')
|
||||
a=p.parse_args();source=a.source.resolve();manifest=json.loads((ROOT/'upstream/manifest.json').read_text())
|
||||
def run(args,**kwargs):return subprocess.run(args,check=True,**kwargs)
|
||||
# The pinned darling-swift .lfsconfig points at the retired git-lfs.darlinghq.org; GitHub still serves the objects.
|
||||
LFS_URL='lfs.url=https://github.com/darlinghq/darling-swift.git/info/lfs'
|
||||
# Without these, a checkout writes Git LFS pointer text where a real dylib belongs, which links but crashes.
|
||||
LFS_FILTERS=['-c','filter.lfs.required=true','-c','filter.lfs.smudge=git-lfs smudge -- %f',
|
||||
'-c','filter.lfs.process=git-lfs filter-process','-c','filter.lfs.clean=git-lfs clean -- %f']
|
||||
def submodules(checkout):
|
||||
out=subprocess.run(['git','-C',str(checkout),'submodule','status','--recursive'],text=True,capture_output=True).stdout
|
||||
return [checkout/line.split()[1] for line in out.splitlines() if len(line.split())>1]
|
||||
def pointers(repo):
|
||||
"""Tracked files still checked out as LFS pointer text instead of their real content."""
|
||||
out=subprocess.run(['git','-C',str(repo),'lfs','ls-files'],text=True,capture_output=True).stdout
|
||||
return [f for f in (line.split(maxsplit=2) for line in out.splitlines()) if len(f)==3 and f[1]=='-']
|
||||
def repair(checkout):
|
||||
"""An interrupted fetch leaves a submodule with a wiped index or pointer text and 'submodule update'
|
||||
treats both as up to date, so check every worktree before this checkout becomes the source tree."""
|
||||
for repo in [checkout,*submodules(checkout)]:
|
||||
name=repo.relative_to(checkout) or '.'
|
||||
if repo!=checkout and subprocess.run(['git','-C',str(repo),'status','--porcelain'],text=True,
|
||||
capture_output=True).stdout.strip():
|
||||
print(f'Repairing the interrupted checkout of {name}',flush=True)
|
||||
run(['git','-C',str(repo),'checkout','-f','HEAD'],stdout=subprocess.DEVNULL)
|
||||
if pointers(repo):
|
||||
print(f'Fetching the Git LFS objects of {name} (pointer text is not a library)',flush=True)
|
||||
run(['git','-C',str(repo),'lfs','install','--local'],stdout=subprocess.DEVNULL)
|
||||
run(['git','-C',str(repo),*(['-c',LFS_URL] if 'swift' in name.parts else []),'lfs','pull'],
|
||||
stdout=subprocess.DEVNULL)
|
||||
if pointers(repo):raise SystemExit(f'{name}: Git LFS objects are still missing; install git-lfs and run this again')
|
||||
|
||||
def applies(repo,patch,reverse=False):
|
||||
return subprocess.run(['git','-C',str(repo),'apply',*(['--reverse'] if reverse else []),'--check','-'],input=patch,text=True,
|
||||
stdout=subprocess.DEVNULL,stderr=subprocess.DEVNULL).returncode==0
|
||||
@@ -37,15 +66,19 @@ if not (source/'.git').exists():
|
||||
run(['git','-C',str(checkout),'remote','add','origin',manifest['upstream']])
|
||||
run(['git','-C',str(checkout),'fetch','--depth','1','origin',manifest['revision']])
|
||||
run(['git','-C',str(checkout),'checkout','--detach','FETCH_HEAD'])
|
||||
if subprocess.run(['git','lfs','version'],stdout=subprocess.DEVNULL,stderr=subprocess.DEVNULL).returncode:
|
||||
p.error('Git LFS is required to fetch the pinned sources; install git-lfs first')
|
||||
run(['git','-C',str(checkout),*LFS_FILTERS,'lfs','install','--local'],stdout=subprocess.DEVNULL)
|
||||
print('Initializing Darling submodules (large repositories/LFS assets may take a while)...',flush=True)
|
||||
for attempt in range(1,4):
|
||||
try:
|
||||
run(['git','-C',str(checkout),'-c','lfs.url=https://github.com/darlinghq/darling-swift.git/info/lfs',
|
||||
'submodule','update','--init','--recursive','--depth','1','--progress'])
|
||||
run(['git','-C',str(checkout),'-c',LFS_URL,*LFS_FILTERS,'submodule','update','--init','--recursive',
|
||||
'--depth','1','--jobs',str(a.jobs),'--progress'])
|
||||
break
|
||||
except subprocess.CalledProcessError:
|
||||
if attempt==3:raise
|
||||
print(f'Submodule fetch interrupted (attempt {attempt}/3). Retrying...',flush=True)
|
||||
repair(checkout)
|
||||
checkout.rename(source)
|
||||
|
||||
# Never reset someone else's checkout to make a patch apply.
|
||||
|
||||
Reference in new issue
Block a user