On Tue, 25 Aug 2026 at 08:35, Richard Purdie
<[email protected]> wrote:
> > RPM 6.0 intentionally changed rpmtsRun() to return -1 whenever any
> > scriptlet fails, even non-critical ones like %post where warn_only=True
> > (upstream RPM PR#3819, lib/transaction.cc).
> >
> > Root cause - two changes in RPM 6 lib/transaction.cc vs RPM 4:
> >
> >   1. New field set before warn_only resets rc (transaction.cc:1754):
> >        ts->scriptError = 1;
> >
> >   2. Final exit now ORs in the new flag (transaction.cc:1910):
> >        RPM 4: rc = nfailed ? -1 : 0;
> >        RPM 6: rc = (nfailed || ts->scriptError) ? -1 : 0;
> >
> > Call chain for a failing %post in RPM 4 (exits 0):
> >   runScript()        warn_only=1 -> rc reset to RPMRC_OK
> >   psm.c:896          if (rc) break -> NOT taken, install continues
> >   rpmte.c:823        if (failed) -> NOT taken, rpmteMarkFailed() skipped
> >   transaction.c:1652 if (failed) -> NOT taken, nfailed stays 0
> >   transaction.c:1896 rc = nfailed ? -1 : 0 -> rc=0
> >   Python ts.run()    returns None -> DNF exits 0
> >
> > Call chain for a failing %post in RPM 6 (exits 1):
> >   runScript()         ts->scriptError=1, then rc reset to RPMRC_OK
> >   psm.c:896           if (rc) break -> NOT taken (rc still 0)
> >   rpmte.c:823         if (failed) -> NOT taken (same as RPM 4)
> >   transaction.cc:1652 if (failed) -> NOT taken, nfailed stays 0
> >   transaction.cc:1910 rc = (nfailed || ts->scriptError) ? -1 : 0 -> rc=-1
> >   Python ts.run()     returns [] -> DNF raises "Could not run
> > transaction."
> >                       -> DNF exits 1
> >
> > In both RPM versions, RPMCALLBACK_SCRIPT_ERROR fires and DNF's
> > _scriptError() (dnf/yum/rpmtrans.py:407-418) prints:
> >   "Error in POSTIN scriptlet in rpm package <name>"
> >
> > OE's install_pkgs() already scans for this line and calls
> > failed_postinsts_abort() (package_manager/rpm/__init__.py:210-219).
> > With RPM 4 this path is always reached because DNF exits 0. With RPM 6
> > the CalledProcessError raised by DNF's non-zero exit intercepts
> > execution
> > in _invoke_dnf() before the scan runs.
> >
> > DNF 4 (lib/dnf/base.py:1146-1158) was never updated for this RPM 6
> > behaviour. When ts.run() returns [] with no failed elements it
> > unconditionally raises "Could not run transaction." - the comment at
> > base.py:1147 still describes RPM 4 semantics where this case meant a
> > global error such as a transaction lock failure. There is an open DNF5
> > issue (#2507) but no fix in DNF 4.
> >
> > Fix: detect "Error in POSTIN scriptlet in rpm package" in the DNF output
> > inside _invoke_dnf()'s CalledProcessError handler and return the output
> > instead of calling bb.fatal(), allowing install_pkgs()'s existing
> > scriptlet scan to run as it did with RPM 4.
> >
> > Tested with oe-selftest runtime_test.Postinst.test_failing_postinst:
> >   rpm 4.20.x: PASSED - DNF exits 0, scan path exercised as expected
> >   rpm 6.0.x without fix: FAILED - CalledProcessError before scan reached
> >   rpm 6.0.x with fix: PASSED - scan path restored, bb.fatal() fires
> >
> > References:
> > https://github.com/rpm-software-management/rpm/pull/3819
> >
> > Signed-off-by: Sumanth Gavini <[email protected]>
> > ---
> >  meta/lib/oe/package_manager/rpm/__init__.py | 7 +++++++
> >  1 file changed, 7 insertions(+)
> >
> > diff --git a/meta/lib/oe/package_manager/rpm/__init__.py 
> > b/meta/lib/oe/package_manager/rpm/__init__.py
> > index cd6efe3d3b..ccb4316bd0 100644
> > --- a/meta/lib/oe/package_manager/rpm/__init__.py
> > +++ b/meta/lib/oe/package_manager/rpm/__init__.py
> > @@ -333,6 +333,13 @@ class RpmPM(PackageManager):
> >          except subprocess.CalledProcessError as e:
> >              if print_output:
> >                  e_output = e.output.decode("utf-8")
> > +                # RPM 6 fails the entire transaction when a %post scriptlet
> > +                # fails, causing dnf to exit non-zero. Let install_pkgs 
> > handle
> > +                # scriptlet failures via its existing "Error in POSTIN 
> > scriptlet"
> > +                # scanning rather than treating this as a fatal dnf 
> > invocation error.
> > +                if "Error in POSTIN scriptlet in rpm package" in e_output:
> > +                    bb.note(e_output)
> > +                    return e_output
> >                  extra_info = ""
> >                  if "install" in dnf_args:
> >                      if "Error: Unable to find a match:" in e_output:
>
> If the transaction fails, isn't that a problem? Wouldn't there be other
> issues after this if we rely on this command having succeeded?
>
> Copying Adam as I know he ran into this with dnf5 as well...

I think a better fix is to not suppress the exception and rely on the
line being looked for somewhere else in the code tree, but rather
handle the exception in the function caller, and look for needed line
there, e.g. move the check for the line to the exception handler.

Alex
-=-=-=-=-=-=-=-=-=-=-=-
Links: You receive all messages sent to this group.
View/Reply Online (#244931): 
https://lists.openembedded.org/g/openembedded-core/message/244931
Mute This Topic: https://lists.openembedded.org/mt/120914654/21656
Group Owner: [email protected]
Unsubscribe: https://lists.openembedded.org/g/openembedded-core/unsub 
[[email protected]]
-=-=-=-=-=-=-=-=-=-=-=-

Reply via email to