On Mon, 2026-08-24 at 18:33 -0700, Sumanth Gavini via lists.openembedded.org 
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...

Cheers,

Richard


-=-=-=-=-=-=-=-=-=-=-=-
Links: You receive all messages sent to this group.
View/Reply Online (#244204): 
https://lists.openembedded.org/g/openembedded-core/message/244204
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