Skip to content

Commit ac475b1

Browse files
committed
portdbapi: aux_get retry for unexpected process returncode
Retry for an intermittent unexpected bash returncode which annoyingly occurs in CI runs with forkserver (bug 965132). Bug: https://bugs.gentoo.org/965132 Signed-off-by: Zac Medico <[email protected]>
1 parent cc4dbc0 commit ac475b1

File tree

1 file changed

+56
-59
lines changed

1 file changed

+56
-59
lines changed

lib/portage/dbapi/porttree.py

Lines changed: 56 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -752,25 +752,51 @@ async def async_aux_get(self, mycpv, mylist, mytree=None, myrepo=None, loop=None
752752

753753
mydata, ebuild_hash = self._pull_valid_cache(mycpv, myebuild, mylocation)
754754

755-
if mydata is not None:
756-
future = loop.create_future()
757-
self._aux_get_return(
758-
future,
759-
mycpv,
760-
mylist,
761-
myebuild,
762-
ebuild_hash,
763-
mydata,
764-
mylocation,
765-
cache_me,
766-
None,
767-
)
768-
return future.result()
755+
proc = None
756+
if mydata is None:
757+
if myebuild in self._broken_ebuilds:
758+
raise PortageKeyError(mycpv)
759+
760+
# Retry for an intermittent unexpected bash returncode which
761+
# annoyingly occurs in CI runs with forkserver (bug 965132).
762+
tries = 3
763+
while tries > 0:
764+
tries -= 1
765+
proc = await self._run_metadata_phase(mycpv, mylocation, ebuild_hash)
766+
767+
if proc.returncode != os.EX_OK:
768+
if proc.returncode != 1:
769+
writemsg(
770+
_(
771+
"!!! aux_get(): metadata phase for package '%(pkg)s' failed with unexpected returncode %(returncode)s\n"
772+
)
773+
% {"pkg": mycpv, "returncode": proc.returncode},
774+
noiselevel=-1,
775+
)
776+
# Only retry for an unexpected returncode.
777+
if tries > 0:
778+
continue
779+
self._broken_ebuilds.add(myebuild)
780+
raise PortageKeyError(mycpv)
769781

770-
if myebuild in self._broken_ebuilds:
771-
raise PortageKeyError(mycpv)
782+
mydata = proc.metadata
783+
break
772784

773-
proc = None
785+
return self._aux_get_return(
786+
mycpv,
787+
mylist,
788+
myebuild,
789+
ebuild_hash,
790+
mydata,
791+
mylocation,
792+
cache_me,
793+
)
794+
795+
async def _run_metadata_phase(
796+
self, mycpv, mylocation, ebuild_hash
797+
) -> EbuildMetadataPhase:
798+
799+
loop = self._event_loop
774800
deallocate_config = None
775801
async with contextlib.AsyncExitStack() as stack:
776802
try:
@@ -800,21 +826,6 @@ async def async_aux_get(self, mycpv, mylist, mytree=None, myrepo=None, loop=None
800826
deallocate_config=deallocate_config,
801827
)
802828

803-
future = loop.create_future()
804-
proc.addExitListener(
805-
functools.partial(
806-
self._aux_get_return,
807-
future,
808-
mycpv,
809-
mylist,
810-
myebuild,
811-
ebuild_hash,
812-
mydata,
813-
mylocation,
814-
cache_me,
815-
)
816-
)
817-
future.add_done_callback(functools.partial(self._aux_get_cancel, proc))
818829
proc.start()
819830

820831
finally:
@@ -824,46 +835,32 @@ async def async_aux_get(self, mycpv, mylist, mytree=None, myrepo=None, loop=None
824835
if proc is None or not proc.isAlive():
825836
deallocate_config.done() or deallocate_config.cancel()
826837
else:
827-
await deallocate_config
838+
try:
839+
await deallocate_config
840+
except asyncio.CancelledError:
841+
proc.cancel()
842+
raise
828843

829844
# After deallocate_config is done, release self._doebuild_settings_lock
830-
# by leaving the stack context, and wait for proc to finish and
831-
# trigger a call to self._aux_get_return.
832-
return await future
833-
834-
@staticmethod
835-
def _aux_get_cancel(proc, future):
836-
if future.cancelled() and proc.returncode is None:
845+
# by leaving the stack context, and wait for proc to finish.
846+
try:
847+
await proc.async_wait()
848+
except asyncio.CancelledError:
837849
proc.cancel()
850+
raise
851+
852+
return proc
838853

839854
def _aux_get_return(
840855
self,
841-
future,
842856
mycpv,
843857
mylist,
844858
myebuild,
845859
ebuild_hash,
846860
mydata,
847861
mylocation,
848862
cache_me,
849-
proc,
850863
):
851-
if future.cancelled():
852-
return
853-
if proc is not None:
854-
if proc.returncode != os.EX_OK:
855-
if proc.returncode != 1:
856-
writemsg(
857-
_(
858-
"!!! aux_get(): metadata phase for package '%(pkg)s' failed with unexpected returncode %(returncode)s\n"
859-
)
860-
% {"pkg": mycpv, "returncode": proc.returncode},
861-
noiselevel=-1,
862-
)
863-
self._broken_ebuilds.add(myebuild)
864-
future.set_exception(PortageKeyError(mycpv))
865-
return
866-
mydata = proc.metadata
867864
mydata["repository"] = self.repositories.get_name_for_location(mylocation)
868865
mydata["_mtime_"] = ebuild_hash.mtime
869866
eapi = mydata.get("EAPI")
@@ -882,7 +879,7 @@ def _aux_get_return(
882879
aux_cache[x] = mydata.get(x, "")
883880
self._aux_cache[mycpv] = aux_cache
884881

885-
future.set_result(returnme)
882+
return returnme
886883

887884
def getFetchMap(self, mypkg, useflags=None, mytree=None):
888885
"""

0 commit comments

Comments
 (0)