Skip to content

Commit 43b79e3

Browse files
committed
dnf5: Print details about concurrent running transaction
1 parent 1c39557 commit 43b79e3

File tree

1 file changed

+66
-0
lines changed

1 file changed

+66
-0
lines changed

dnf5/context.cpp

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@
4242
#include <libdnf5/utils/fs/file.hpp>
4343
#include <libdnf5/utils/patterns.hpp>
4444
#include <rpm/rpmtypes.h>
45+
#include <signal.h>
4546

4647
#include <algorithm>
4748
#include <cctype>
@@ -58,6 +59,47 @@ namespace dnf5 {
5859

5960
namespace {
6061

62+
// Helper function to format active transaction information for error messages
63+
std::string format_active_transaction_info(const libdnf5::base::ActiveTransactionInfo & info) {
64+
std::string result;
65+
66+
if (!info.get_description().empty()) {
67+
result += libdnf5::utils::sformat(_("Command: {}"), info.get_description());
68+
}
69+
70+
if (info.get_pid() > 0) {
71+
if (!result.empty()) {
72+
result += "\n";
73+
}
74+
if (kill(info.get_pid(), 0) == 0) {
75+
result += libdnf5::utils::sformat(_("Process ID: {} (still running)"), info.get_pid());
76+
} else {
77+
result += libdnf5::utils::sformat(_("Process ID: {}"), info.get_pid());
78+
}
79+
}
80+
81+
if (info.get_start_time() > 0) {
82+
if (!result.empty()) {
83+
result += "\n";
84+
}
85+
result +=
86+
libdnf5::utils::sformat(_("Started: {}"), libdnf5::utils::string::format_epoch(info.get_start_time()));
87+
}
88+
89+
if (!info.get_comment().empty()) {
90+
if (!result.empty()) {
91+
result += "\n";
92+
}
93+
result += libdnf5::utils::sformat(_("Comment: {}"), info.get_comment());
94+
}
95+
96+
if (!result.empty()) {
97+
result = _("Details about the currently running transaction:\n") + result;
98+
}
99+
100+
return result;
101+
}
102+
61103
// The `KeyImportRepoCB` class implements callback only for importing repository key.
62104
class KeyImportRepoCB : public libdnf5::repo::RepoCallbacks2_1 {
63105
public:
@@ -377,6 +419,18 @@ void Context::Impl::store_offline(libdnf5::base::Transaction & transaction) {
377419
if (result != libdnf5::base::Transaction::TransactionRunResult::SUCCESS) {
378420
print_error(libdnf5::utils::sformat(
379421
_("Transaction failed: {}"), libdnf5::base::Transaction::transaction_result_to_string(result)));
422+
423+
// For transaction lock errors, provide detailed information about the running transaction
424+
if (result == libdnf5::base::Transaction::TransactionRunResult::ERROR_LOCK) {
425+
auto * active_info = transaction.get_concurrent_transaction();
426+
if (active_info) {
427+
auto info_str = format_active_transaction_info(*active_info);
428+
if (!info_str.empty()) {
429+
print_error(info_str);
430+
}
431+
}
432+
}
433+
380434
for (auto const & entry : transaction.get_gpg_signature_problems()) {
381435
print_error(entry);
382436
}
@@ -530,6 +584,18 @@ void Context::Impl::download_and_run(libdnf5::base::Transaction & transaction) {
530584
if (result != libdnf5::base::Transaction::TransactionRunResult::SUCCESS) {
531585
print_error(libdnf5::utils::sformat(
532586
_("Transaction failed: {}"), libdnf5::base::Transaction::transaction_result_to_string(result)));
587+
588+
// For transaction lock errors, provide detailed information about the running transaction
589+
if (result == libdnf5::base::Transaction::TransactionRunResult::ERROR_LOCK) {
590+
auto * active_info = transaction.get_concurrent_transaction();
591+
if (active_info) {
592+
auto info_str = format_active_transaction_info(*active_info);
593+
if (!info_str.empty()) {
594+
print_error(info_str);
595+
}
596+
}
597+
}
598+
533599
for (auto const & entry : transaction.get_gpg_signature_problems()) {
534600
print_error(entry);
535601
}

0 commit comments

Comments
 (0)