Skip to content

Commit 6b96e14

Browse files
committed
dnf5: Print details about concurrent running transaction
1 parent 1ccd277 commit 6b96e14

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>
@@ -60,6 +61,47 @@ namespace {
6061

6162
constexpr const char * STORED_REPO_PREFIX = "@stored_transaction";
6263

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

0 commit comments

Comments
 (0)