Mercurial > hg
view tests/test-resolve.t @ 35428:71427ff1dff8
workers: handling exceptions in windows workers
This adds handling of exceptions from worker threads and resurfaces them as if the function ran without workers.
If any of the threads throws, the main thread kills all running threads giving them 5 sec to handle the interruption and raises the first exception received.
We don't have to join threads if is_alive() is false
Test Plan:
Ran multiple updates/enable/disable sparse profile and things worked well
Ran test on CentOS- all tests passing on @ passed here
Added a forged exception into the worker code and got it properly resurfaced and the rest of workers killed: P58642088
PS C:\open\<repo>> ..\facebook-hg-rpms\build\hg\hg.exe --config extensions.fsmonitor=! sparse --enable-profile <profile>
updating [==> ] 1300/39166 1m57sException in thread Thread-3:
Traceback (most recent call last):
File "C:\open\facebook-hg-rpms\build\hg\hg-python\lib\threading.py", line 801, in __bootstrap_inner
self.run()
File "C:\open\facebook-hg-rpms\build\hg\mercurial\worker.py", line 244, in run
raise e
Exception: Forged exception
Exception in thread Thread-2:
Traceback (most recent call last):
File "C:\open\facebook-hg-rpms\build\hg\hg-python\lib\threading.py", line 801, in __bootstrap_inner
self.run()
File "C:\open\facebook-hg-rpms\build\hg\mercurial\worker.py", line 244, in run
raise e
Exception: Forged exception
<...>
Traceback (most recent call last):
File "C:\open\facebook-hg-rpms\build\hg\hgexe.py", line 41, in <module>
dispatch.run()
File "C:\open\facebook-hg-rpms\build\hg\mercurial\dispatch.py", line 85, in run
status = (dispatch(req) or 0) & 255
File "C:\open\facebook-hg-rpms\build\hg\mercurial\dispatch.py", line 173, in dispatch
ret = _runcatch(req)
File "C:\open\facebook-hg-rpms\build\hg\mercurial\dispatch.py", line 324, in _runcatch
return _callcatch(ui, _runcatchfunc)
File "C:\open\facebook-hg-rpms\build\hg\mercurial\dispatch.py", line 332, in _callcatch
return scmutil.callcatch(ui, func)
File "C:\open\facebook-hg-rpms\build\hg\mercurial\scmutil.py", line 154, in callcatch
return func()
File "C:\open\facebook-hg-rpms\build\hg\mercurial\dispatch.py", line 314, in _runcatchfunc
return _dispatch(req)
File "C:\open\facebook-hg-rpms\build\hg\mercurial\dispatch.py", line 951, in _dispatch
cmdpats, cmdoptions)
File "C:\open\facebook-hg-rpms\build\hg\hg-python\lib\site-packages\remotefilelog\__init__.py", line 415, in runcommand
return orig(lui, repo, *args, **kwargs)
File "C:\open\facebook-hg-rpms\build\hg\hg-python\lib\site-packages\hgext3rd\undo.py", line 118, in _runcommandwrapper
result = orig(lui, repo, cmd, fullargs, *args)
File "C:\open\facebook-hg-rpms\build\hg\hgext\journal.py", line 84, in runcommand
return orig(lui, repo, cmd, fullargs, *args)
File "C:\open\facebook-hg-rpms\build\hg\hg-python\lib\site-packages\hgext3rd\perftweaks.py", line 268, in _tracksparseprofiles
res = runcommand(lui, repo, *args)
File "C:\open\facebook-hg-rpms\build\hg\hg-python\lib\site-packages\hgext3rd\perftweaks.py", line 256, in _trackdirstatesizes
res = runcommand(lui, repo, *args)
File "C:\open\facebook-hg-rpms\build\hg\hg-python\lib\site-packages\hgext3rd\copytrace.py", line 144, in _runcommand
return orig(lui, repo, cmd, fullargs, ui, *args, **kwargs)
File "C:\open\facebook-hg-rpms\build\hg\hg-python\lib\site-packages\hgext3rd\fbamend\hiddenoverride.py", line 119, in runcommand
result = orig(lui, repo, cmd, fullargs, *args)
File "C:\open\facebook-hg-rpms\build\hg\mercurial\dispatch.py", line 712, in runcommand
ret = _runcommand(ui, options, cmd, d)
File "C:\open\facebook-hg-rpms\build\hg\mercurial\dispatch.py", line 959, in _runcommand
return cmdfunc()
File "C:\open\facebook-hg-rpms\build\hg\mercurial\dispatch.py", line 948, in <lambda>
d = lambda: util.checksignature(func)(ui, *args, **strcmdopt)
File "C:\open\facebook-hg-rpms\build\hg\mercurial\util.py", line 1183, in check
return func(*args, **kwargs)
File "C:\open\facebook-hg-rpms\build\hg\hg-python\lib\site-packages\hgext3rd\fbsparse.py", line 860, in sparse
disableprofile=disableprofile, force=force)
File "C:\open\facebook-hg-rpms\build\hg\hg-python\lib\site-packages\hgext3rd\fbsparse.py", line 949, in _config
len, _refresh(ui, repo, oldstatus, oldsparsematch, force))
File "C:\open\facebook-hg-rpms\build\hg\hg-python\lib\site-packages\hgext3rd\fbsparse.py", line 1116, in _refresh
mergemod.applyupdates(repo, typeactions, repo[None], repo['.'], False)
File "C:\open\facebook-hg-rpms\build\hg\hg-python\lib\site-packages\remotefilelog\__init__.py", line 311, in applyupdates
return orig(repo, actions, wctx, mctx, overwrite, labels=labels)
File "C:\open\facebook-hg-rpms\build\hg\mercurial\merge.py", line 1464, in applyupdates
for i, item in prog:
File "C:\open\facebook-hg-rpms\build\hg\mercurial\worker.py", line 286, in _windowsworker
raise t.exception
Exception: Forged exception
PS C:\open\ovrsource>
Differential Revision: https://phab.mercurial-scm.org/D1459
author | Wojciech Lis <wlis@fb.com> |
---|---|
date | Mon, 20 Nov 2017 10:27:41 -0800 |
parents | 4441705b7111 |
children | 41ef02ba329b |
line wrap: on
line source
test that a commit clears the merge state. $ hg init repo $ cd repo $ echo foo > file1 $ echo foo > file2 $ hg commit -Am 'add files' adding file1 adding file2 $ echo bar >> file1 $ echo bar >> file2 $ hg commit -Am 'append bar to files' create a second head with conflicting edits $ hg up -C 0 2 files updated, 0 files merged, 0 files removed, 0 files unresolved $ echo baz >> file1 $ echo baz >> file2 $ hg commit -Am 'append baz to files' created new head create a third head with no conflicting edits $ hg up -qC 0 $ echo foo > file3 $ hg commit -Am 'add non-conflicting file' adding file3 created new head failing merge $ hg up -qC 2 $ hg merge --tool=internal:fail 1 0 files updated, 0 files merged, 0 files removed, 2 files unresolved use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon [1] resolve -l should contain unresolved entries $ hg resolve -l U file1 U file2 $ hg resolve -l --no-status file1 file2 resolving an unknown path should emit a warning, but not for -l $ hg resolve -m does-not-exist arguments do not match paths that need resolving $ hg resolve -l does-not-exist tell users how they could have used resolve $ mkdir nested $ cd nested $ hg resolve -m file1 arguments do not match paths that need resolving (try: hg resolve -m path:file1) $ hg resolve -m file1 filez arguments do not match paths that need resolving (try: hg resolve -m path:file1 path:filez) $ hg resolve -m path:file1 path:filez $ hg resolve -l R file1 U file2 $ hg resolve -m filez file2 arguments do not match paths that need resolving (try: hg resolve -m path:filez path:file2) $ hg resolve -m path:filez path:file2 (no more unresolved files) $ hg resolve -l R file1 R file2 cleanup $ hg resolve -u $ cd .. $ rmdir nested don't allow marking or unmarking driver-resolved files $ cat > $TESTTMP/markdriver.py << EOF > '''mark and unmark files as driver-resolved''' > from mercurial import merge, registrar, scmutil > cmdtable = {} > command = registrar.command(cmdtable) > @command(b'markdriver', > [('u', 'unmark', None, '')], > 'FILE...') > def markdriver(ui, repo, *pats, **opts): > wlock = repo.wlock() > try: > ms = merge.mergestate.read(repo) > m = scmutil.match(repo[None], pats, opts) > for f in ms: > if not m(f): > continue > if not opts['unmark']: > ms.mark(f, 'd') > else: > ms.mark(f, 'u') > ms.commit() > finally: > wlock.release() > EOF $ hg --config extensions.markdriver=$TESTTMP/markdriver.py markdriver file1 $ hg resolve --list D file1 U file2 $ hg resolve --mark file1 not marking file1 as it is driver-resolved this should not print out file1 $ hg resolve --mark --all (no more unresolved files -- run "hg resolve --all" to conclude) $ hg resolve --mark 'glob:file*' (no more unresolved files -- run "hg resolve --all" to conclude) $ hg resolve --list D file1 R file2 $ hg resolve --unmark file1 not unmarking file1 as it is driver-resolved (no more unresolved files -- run "hg resolve --all" to conclude) $ hg resolve --unmark --all $ hg resolve --list D file1 U file2 $ hg --config extensions.markdriver=$TESTTMP/markdriver.py markdriver --unmark file1 $ hg resolve --list U file1 U file2 resolve the failure $ echo resolved > file1 $ hg resolve -m file1 resolve -l should show resolved file as resolved $ hg resolve -l R file1 U file2 $ hg resolve -l -Tjson [ { "path": "file1", "status": "R" }, { "path": "file2", "status": "U" } ] resolve -m without paths should mark all resolved $ hg resolve -m (no more unresolved files) $ hg commit -m 'resolved' resolve -l should be empty after commit $ hg resolve -l $ hg resolve -l -Tjson [ ] resolve --all should abort when no merge in progress $ hg resolve --all abort: resolve command not applicable when not merging [255] resolve -m should abort when no merge in progress $ hg resolve -m abort: resolve command not applicable when not merging [255] can not update or merge when there are unresolved conflicts $ hg up -qC 0 $ echo quux >> file1 $ hg up 1 merging file1 warning: conflicts while merging file1! (edit, then use 'hg resolve --mark') 1 files updated, 0 files merged, 0 files removed, 1 files unresolved use 'hg resolve' to retry unresolved file merges [1] $ hg up 0 abort: outstanding merge conflicts [255] $ hg merge 2 abort: outstanding merge conflicts [255] $ hg merge --force 2 abort: outstanding merge conflicts [255] set up conflict-free merge $ hg up -qC 3 $ hg merge 1 2 files updated, 0 files merged, 0 files removed, 0 files unresolved (branch merge, don't forget to commit) resolve --all should do nothing in merge without conflicts $ hg resolve --all (no more unresolved files) resolve -m should do nothing in merge without conflicts $ hg resolve -m (no more unresolved files) get back to conflicting state $ hg up -qC 2 $ hg merge --tool=internal:fail 1 0 files updated, 0 files merged, 0 files removed, 2 files unresolved use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon [1] resolve without arguments should suggest --all $ hg resolve abort: no files or directories specified (use --all to re-merge all unresolved files) [255] resolve --all should re-merge all unresolved files $ hg resolve --all merging file1 merging file2 warning: conflicts while merging file1! (edit, then use 'hg resolve --mark') warning: conflicts while merging file2! (edit, then use 'hg resolve --mark') [1] $ cat file1.orig foo baz $ cat file2.orig foo baz .orig files should exists where specified $ hg resolve --all --verbose --config 'ui.origbackuppath=.hg/origbackups' merging file1 creating directory: $TESTTMP/repo/.hg/origbackups merging file2 warning: conflicts while merging file1! (edit, then use 'hg resolve --mark') warning: conflicts while merging file2! (edit, then use 'hg resolve --mark') [1] $ ls .hg/origbackups file1 file2 $ grep '<<<' file1 > /dev/null $ grep '<<<' file2 > /dev/null resolve <file> should re-merge file $ echo resolved > file1 $ hg resolve -q file1 warning: conflicts while merging file1! (edit, then use 'hg resolve --mark') [1] $ grep '<<<' file1 > /dev/null test .orig behavior with resolve $ hg resolve -q file1 --tool "sh -c 'f --dump \"$TESTTMP/repo/file1.orig\"'" $TESTTMP/repo/file1.orig: >>> foo baz <<< resolve <file> should do nothing if 'file' was marked resolved $ echo resolved > file1 $ hg resolve -m file1 $ hg resolve -q file1 $ cat file1 resolved insert unsupported advisory merge record $ hg --config extensions.fakemergerecord=$TESTDIR/fakemergerecord.py fakemergerecord -x $ hg debugmergestate * version 2 records local: 57653b9f834a4493f7240b0681efcb9ae7cab745 other: dc77451844e37f03f5c559e3b8529b2b48d381d1 labels: local: working copy other: merge rev unrecognized entry: x advisory record file extras: file1 (ancestorlinknode = 99726c03216e233810a2564cbc0adfe395007eac) file: file1 (record type "F", state "r", hash 60b27f004e454aca81b0480209cce5081ec52390) local path: file1 (flags "") ancestor path: file1 (node 2ed2a3912a0b24502043eae84ee4b279c18b90dd) other path: file1 (node 6f4310b00b9a147241b071a60c28a650827fb03d) file extras: file2 (ancestorlinknode = 99726c03216e233810a2564cbc0adfe395007eac) file: file2 (record type "F", state "u", hash cb99b709a1978bd205ab9dfd4c5aaa1fc91c7523) local path: file2 (flags "") ancestor path: file2 (node 2ed2a3912a0b24502043eae84ee4b279c18b90dd) other path: file2 (node 6f4310b00b9a147241b071a60c28a650827fb03d) $ hg resolve -l R file1 U file2 insert unsupported mandatory merge record $ hg --config extensions.fakemergerecord=$TESTDIR/fakemergerecord.py fakemergerecord -X $ hg debugmergestate * version 2 records local: 57653b9f834a4493f7240b0681efcb9ae7cab745 other: dc77451844e37f03f5c559e3b8529b2b48d381d1 labels: local: working copy other: merge rev file extras: file1 (ancestorlinknode = 99726c03216e233810a2564cbc0adfe395007eac) file: file1 (record type "F", state "r", hash 60b27f004e454aca81b0480209cce5081ec52390) local path: file1 (flags "") ancestor path: file1 (node 2ed2a3912a0b24502043eae84ee4b279c18b90dd) other path: file1 (node 6f4310b00b9a147241b071a60c28a650827fb03d) file extras: file2 (ancestorlinknode = 99726c03216e233810a2564cbc0adfe395007eac) file: file2 (record type "F", state "u", hash cb99b709a1978bd205ab9dfd4c5aaa1fc91c7523) local path: file2 (flags "") ancestor path: file2 (node 2ed2a3912a0b24502043eae84ee4b279c18b90dd) other path: file2 (node 6f4310b00b9a147241b071a60c28a650827fb03d) unrecognized entry: X mandatory record $ hg resolve -l abort: unsupported merge state records: X (see https://mercurial-scm.org/wiki/MergeStateRecords for more information) [255] $ hg resolve -ma abort: unsupported merge state records: X (see https://mercurial-scm.org/wiki/MergeStateRecords for more information) [255] $ hg summary warning: merge state has unsupported record types: X parent: 2:57653b9f834a append baz to files parent: 1:dc77451844e3 append bar to files branch: default commit: 2 modified, 2 unknown (merge) update: 2 new changesets (update) phases: 5 draft update --clean shouldn't abort on unsupported records $ hg up -qC 1 $ hg debugmergestate no merge state found test crashed merge with empty mergestate $ mkdir .hg/merge $ touch .hg/merge/state resolve -l should be empty $ hg resolve -l $ cd ..