refactor: fix cppcoreguidelines-avoid-do-while warnings (#6527)

* fix: avoid do-while in tr_sys_file_lock()

* fix: avoid do-while in BitfieldTest

* chore: set cppcoreguidelines-avoid-do-while.IgnoreMacros

* fix: avoid do-while in FileList::Impl::onRowActivated()

* fix: avoid do-while in tr_spawn_async_in_parent()

* fix: avoid do-while in handle_sigchld()

* fixup! fix: avoid do-while in tr_spawn_async_in_parent()

* fixup! fix: avoid do-while in FileList::Impl::onRowActivated()

* fixup! fix: avoid do-while in tr_spawn_async_in_parent()

fix fd leak regression

* fixup! fix: avoid do-while in tr_spawn_async_in_parent()
This commit is contained in:
Charles Kerr 2024-01-20 16:56:42 -06:00 committed by GitHub
parent e408aa0741
commit 468de87076
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 112 additions and 107 deletions

View File

@ -23,5 +23,6 @@ Checks: >
-readability-redundant-access-specifiers -readability-redundant-access-specifiers
CheckOptions: CheckOptions:
misc-non-private-member-variables-in-classes.IgnoreClassesWithAllMemberVariablesBeingPublic: true - { key: cppcoreguidelines-avoid-do-while.IgnoreMacros, value: true }
modernize-pass-by-value.ValuesOnly: true - { key: misc-non-private-member-variables-in-classes.IgnoreClassesWithAllMemberVariablesBeingPublic, value: true }
- { key: modernize-pass-by-value.ValuesOnly, value: true }

View File

@ -37,6 +37,7 @@
#include <algorithm> #include <algorithm>
#include <list> #include <list>
#include <memory> #include <memory>
#include <optional>
#include <queue> #include <queue>
#include <stack> #include <stack>
#include <string> #include <string>
@ -658,7 +659,7 @@ void renderPriority(Gtk::CellRenderer* renderer, Gtk::TreeModel::const_iterator
} }
/* build a filename from tr_torrentGetCurrentDir() + the model's FC_LABELs */ /* build a filename from tr_torrentGetCurrentDir() + the model's FC_LABELs */
std::string buildFilename(tr_torrent const* tor, Gtk::TreeModel::iterator const& iter) std::string build_filename(tr_torrent const* tor, Gtk::TreeModel::iterator const& iter)
{ {
std::vector<std::string> tokens; std::vector<std::string> tokens;
for (auto child = iter; child; child = child->parent()) for (auto child = iter; child; child = child->parent())
@ -671,37 +672,52 @@ std::string buildFilename(tr_torrent const* tor, Gtk::TreeModel::iterator const&
return Glib::build_filename(tokens); return Glib::build_filename(tokens);
} }
std::optional<std::string> get_filename_to_open(tr_torrent const* tor, Gtk::TreeModel::iterator const& iter)
{
auto file = Gio::File::create_for_path(build_filename(tor, iter));
// if the selected file is complete, use it
if (iter->get_value(file_cols.prog) == 100 && file->query_exists())
{
return file->get_path();
}
// use nearest existing ancestor instead
for (;;)
{
file = file->get_parent();
if (!file)
{
return {};
}
if (file->query_exists())
{
return file->get_path();
}
}
}
} // namespace } // namespace
void FileList::Impl::onRowActivated(Gtk::TreeModel::Path const& path, Gtk::TreeViewColumn* /*col*/) void FileList::Impl::onRowActivated(Gtk::TreeModel::Path const& path, Gtk::TreeViewColumn* /*col*/)
{ {
bool handled = false; auto const* const tor = core_->find_torrent(torrent_id_);
if (tor == nullptr)
if (auto const* tor = core_->find_torrent(torrent_id_); tor != nullptr)
{ {
if (auto const iter = store_->get_iter(path); iter) return;
{
auto filename = buildFilename(tor, iter);
auto const prog = iter->get_value(file_cols.prog);
/* if the file's not done, walk up the directory tree until we find
* an ancestor that exists, and open that instead */
if (!filename.empty() && (prog < 100 || !Glib::file_test(filename, TR_GLIB_FILE_TEST(EXISTS))))
{
do
{
filename = Glib::path_get_dirname(filename);
} while (!filename.empty() && !Glib::file_test(filename, TR_GLIB_FILE_TEST(EXISTS)));
}
if (handled = !filename.empty(); handled)
{
gtr_open_file(filename);
}
}
} }
// return handled; auto const iter = store_->get_iter(path);
if (!iter)
{
return;
}
if (auto const filename = get_filename_to_open(tor, iter); filename)
{
gtr_open_file(*filename);
}
} }
bool FileList::Impl::onViewPathToggled(Gtk::TreeViewColumn* col, Gtk::TreeModel::Path const& path) bool FileList::Impl::onViewPathToggled(Gtk::TreeViewColumn* col, Gtk::TreeModel::Path const& path)

View File

@ -977,8 +977,6 @@ bool tr_sys_file_lock([[maybe_unused]] tr_sys_file_t handle, [[maybe_unused]] in
TR_ASSERT( TR_ASSERT(
!!(operation & TR_SYS_FILE_LOCK_SH) + !!(operation & TR_SYS_FILE_LOCK_EX) + !!(operation & TR_SYS_FILE_LOCK_UN) == 1); !!(operation & TR_SYS_FILE_LOCK_SH) + !!(operation & TR_SYS_FILE_LOCK_EX) + !!(operation & TR_SYS_FILE_LOCK_UN) == 1);
bool ret = false;
#if defined(F_OFD_SETLK) #if defined(F_OFD_SETLK)
struct flock fl = {}; struct flock fl = {};
@ -1000,58 +998,60 @@ bool tr_sys_file_lock([[maybe_unused]] tr_sys_file_t handle, [[maybe_unused]] in
fl.l_whence = SEEK_SET; fl.l_whence = SEEK_SET;
do int const native_operation = (operation & TR_SYS_FILE_LOCK_NB) != 0 ? F_OFD_SETLK : F_OFD_SETLKW;
{
ret = fcntl(handle, (operation & TR_SYS_FILE_LOCK_NB) != 0 ? F_OFD_SETLK : F_OFD_SETLKW, &fl) != -1;
} while (!ret && errno == EINTR);
if (!ret && errno == EAGAIN) auto result = std::optional<bool>{};
while (!result)
{ {
errno = EWOULDBLOCK; if (fcntl(handle, native_operation, &fl) != -1)
{
result = true;
}
else if (errno != EINTR)
{
result = false;
}
} }
#elif defined(HAVE_FLOCK) #elif defined(HAVE_FLOCK)
int native_operation = 0; int const native_operation = //
(((operation & TR_SYS_FILE_LOCK_SH) != 0) ? LOCK_SH : 0) | //
(((operation & TR_SYS_FILE_LOCK_EX) != 0) ? LOCK_EX : 0) | //
(((operation & TR_SYS_FILE_LOCK_NB) != 0) ? LOCK_NB : 0) | //
(((operation & TR_SYS_FILE_LOCK_UN) != 0) ? LOCK_UN : 0);
if ((operation & TR_SYS_FILE_LOCK_SH) != 0) auto result = std::optional<bool>{};
while (!result)
{ {
native_operation |= LOCK_SH; if (flock(handle, native_operation) != -1)
{
result = true;
}
else if (errno != EINTR)
{
result = false;
}
} }
if ((operation & TR_SYS_FILE_LOCK_EX) != 0)
{
native_operation |= LOCK_EX;
}
if ((operation & TR_SYS_FILE_LOCK_NB) != 0)
{
native_operation |= LOCK_NB;
}
if ((operation & TR_SYS_FILE_LOCK_UN) != 0)
{
native_operation |= LOCK_UN;
}
do
{
ret = flock(handle, native_operation) != -1;
} while (!ret && errno == EINTR);
#else #else
errno = ENOSYS; errno = ENOSYS;
ret = false; auto const result = std::optional<bool>{ false };
#endif #endif
if (error != nullptr && !ret) if (!*result && errno == EAGAIN)
{
errno = EWOULDBLOCK;
}
if (error != nullptr && !*result)
{ {
error->set_from_errno(errno); error->set_from_errno(errno);
} }
return ret; return *result;
} }
std::string tr_sys_dir_get_current(tr_error* error) std::string tr_sys_dir_get_current(tr_error* error)

View File

@ -29,15 +29,18 @@ namespace
{ {
void handle_sigchld(int /*i*/) void handle_sigchld(int /*i*/)
{ {
int rc = 0; for (;;)
do
{ {
/* FIXME: Only check for our own PIDs */ // FIXME: only check for our own PIDs
rc = waitpid(-1, nullptr, WNOHANG); auto const res = waitpid(-1, nullptr, WNOHANG);
} while (rc > 0 || (rc == -1 && errno == EINTR));
/* FIXME: Call old handler, if any */ if ((res == 0) || (res == -1 && errno != EINTR))
{
break;
}
}
// FIXME: Call old handler, if any
} }
void set_system_error(tr_error* error, int code, std::string_view what) void set_system_error(tr_error* error, int code, std::string_view what)
@ -82,34 +85,29 @@ void set_system_error(tr_error* error, int code, std::string_view what)
[[nodiscard]] bool tr_spawn_async_in_parent(int pipe_fd, tr_error* error) [[nodiscard]] bool tr_spawn_async_in_parent(int pipe_fd, tr_error* error)
{ {
int child_errno = 0; auto child_errno = int{};
ssize_t count = 0; auto n_read = ssize_t{};
for (auto done = false; !done;)
static_assert(sizeof(child_errno) == sizeof(errno));
do
{ {
count = read(pipe_fd, &child_errno, sizeof(child_errno)); n_read = read(pipe_fd, &child_errno, sizeof(child_errno));
} while (count == -1 && errno == EINTR); done = n_read != -1 || errno != EINTR;
}
close(pipe_fd); close(pipe_fd);
if (count == -1) if (n_read == 0) // child successfully exec'ed
{ {
/* Read failed (what to do?) */ return true;
} }
else if (count == 0)
{
/* Child successfully exec-ed */
}
else
{
TR_ASSERT((size_t)count == sizeof(child_errno));
if (n_read > 0) // child errno was set
{
TR_ASSERT(static_cast<size_t>(n_read) == sizeof(child_errno));
set_system_error(error, child_errno, "Child process setup"); set_system_error(error, child_errno, "Child process setup");
return false; return false;
} }
// read failed (what to do?)
return true; return true;
} }
} // namespace } // namespace

View File

@ -38,6 +38,7 @@ Checks: >
-readability-redundant-access-specifiers, # keep: 'private' vs 'private slots' -readability-redundant-access-specifiers, # keep: 'private' vs 'private slots'
CheckOptions: CheckOptions:
- { key: cppcoreguidelines-avoid-do-while.IgnoreMacros, value: true }
- { key: readability-identifier-naming.ClassCase, value: CamelCase } - { key: readability-identifier-naming.ClassCase, value: CamelCase }
- { key: readability-identifier-naming.ClassMethodCase, value: camelBack } - { key: readability-identifier-naming.ClassMethodCase, value: camelBack }
- { key: readability-identifier-naming.ConstexprVariableCase, value: CamelCase } - { key: readability-identifier-naming.ConstexprVariableCase, value: CamelCase }

View File

@ -34,6 +34,7 @@ Checks: >
-readability-qualified-auto, -readability-qualified-auto,
CheckOptions: CheckOptions:
- { key: cppcoreguidelines-avoid-do-while.IgnoreMacros, value: true }
- { key: readability-identifier-naming.ClassCase, value: CamelCase } - { key: readability-identifier-naming.ClassCase, value: CamelCase }
- { key: readability-identifier-naming.ClassMethodCase, value: camelBack } - { key: readability-identifier-naming.ClassMethodCase, value: camelBack }
- { key: readability-identifier-naming.ConstexprVariableCase, value: CamelCase } - { key: readability-identifier-naming.ConstexprVariableCase, value: CamelCase }

View File

@ -17,34 +17,22 @@
TEST(Bitfield, count) TEST(Bitfield, count)
{ {
auto constexpr IterCount = int{ 10000 }; auto constexpr IterCount = size_t{ 10000U };
for (auto i = 0; i < IterCount; ++i) for (size_t i = 0; i < IterCount; ++i)
{ {
auto const bit_count = 100U + tr_rand_int(1000U);
// generate a random bitfield // generate a random bitfield
tr_bitfield bf(bit_count); auto const bit_count = 100U + tr_rand_int(1000U);
auto bf = tr_bitfield{ bit_count };
for (size_t j = 0, n = tr_rand_int(bit_count); j < n; ++j) for (size_t idx = 0U; idx < bit_count; ++idx)
{ {
bf.set(tr_rand_int(bit_count)); bf.set(idx, tr_rand_int(2U) != 0U);
} }
int begin = tr_rand_int(bit_count); // pick arbitrary endpoints in the 1st and 2nd half of the bitfield
int end = 0; auto const midpt = bit_count / 2U;
do auto const begin = tr_rand_int(midpt);
{ auto const end = midpt + tr_rand_int(midpt);
end = tr_rand_int(bit_count);
} while (end == begin);
// ensure end <= begin
if (end < begin)
{
int const tmp = begin;
begin = end;
end = tmp;
}
// test the bitfield // test the bitfield
unsigned long count1 = {}; unsigned long count1 = {};