mirror of
https://github.com/transmission/transmission.git
synced 2026-02-15 07:26:49 +00:00
fix: race condition when removing torrents in GTK client (#8341)
* fix: race condition crash when removing torrents in GTK client * refactor: remove unused on_remove_done arg from tr_torrentRemove()
This commit is contained in:
@@ -172,8 +172,6 @@ private:
|
||||
void on_torrent_completeness_changed(tr_torrent* tor, tr_completeness completeness, bool was_running);
|
||||
void on_torrent_metadata_changed(tr_torrent* raw_torrent);
|
||||
|
||||
void on_torrent_removal_done(tr_torrent_id_t id, bool succeeded);
|
||||
|
||||
private:
|
||||
Session& core_;
|
||||
|
||||
@@ -928,30 +926,11 @@ void Session::remove_torrent(tr_torrent_id_t id, bool delete_files)
|
||||
|
||||
void Session::Impl::remove_torrent(tr_torrent_id_t const id, bool const delete_files)
|
||||
{
|
||||
auto const& [torrent, _] = find_torrent_by_id(id);
|
||||
if (!torrent)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
auto const on_remove_done = [core = get_core_ptr()](tr_torrent_id_t const removed_id, bool const ok)
|
||||
{
|
||||
Glib::signal_idle().connect_once([core, removed_id, ok]() { core->impl_->on_torrent_removal_done(removed_id, ok); });
|
||||
};
|
||||
|
||||
tr_torrentRemove(&torrent->get_underlying(), delete_files, gtr_file_trash_or_remove, std::move(on_remove_done));
|
||||
}
|
||||
|
||||
void Session::Impl::on_torrent_removal_done(tr_torrent_id_t id, bool succeeded)
|
||||
{
|
||||
if (!succeeded)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (auto const& [torrent, position] = find_torrent_by_id(id); torrent)
|
||||
{
|
||||
get_raw_model()->remove(position);
|
||||
|
||||
tr_torrentRemove(&torrent->get_underlying(), delete_files, gtr_file_trash_or_remove);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -682,13 +682,11 @@ void tr_torrent::stop_now()
|
||||
// By-value: arguments are moved into the session-thread work item.
|
||||
void tr_torrentRemoveInSessionThread(
|
||||
tr_torrent* tor,
|
||||
bool delete_flag,
|
||||
tr_torrent_remove_func remove_func,
|
||||
tr_torrent_remove_done_func on_remove_done) // NOLINT(performance-unnecessary-value-param)
|
||||
bool const delete_flag,
|
||||
tr_torrent_remove_func remove_func) // NOLINT(performance-unnecessary-value-param)
|
||||
{
|
||||
auto const lock = tor->unique_lock();
|
||||
|
||||
bool ok = true;
|
||||
if (delete_flag && tor->has_metainfo())
|
||||
{
|
||||
// ensure the files are all closed and idle before moving
|
||||
@@ -700,32 +698,21 @@ void tr_torrentRemoveInSessionThread(
|
||||
remove_func = tr_sys_path_remove;
|
||||
}
|
||||
|
||||
tr_error error;
|
||||
auto error = tr_error{};
|
||||
tor->files().remove(tor->current_dir(), tor->name(), remove_func, &error);
|
||||
if (error)
|
||||
{
|
||||
ok = false;
|
||||
tor->is_deleting_ = false;
|
||||
|
||||
tor->error().set_local_error(
|
||||
tr_logAddWarnTor(
|
||||
tor,
|
||||
fmt::format(
|
||||
fmt::runtime(_("Couldn't remove all torrent files: {error} ({error_code})")),
|
||||
fmt::arg("error", error.message()),
|
||||
fmt::arg("error_code", error.code())));
|
||||
tr_torrentStop(tor);
|
||||
}
|
||||
}
|
||||
|
||||
if (on_remove_done)
|
||||
{
|
||||
on_remove_done(tor->id(), ok);
|
||||
}
|
||||
|
||||
if (ok)
|
||||
{
|
||||
tr_torrentFreeInSessionThread(tor);
|
||||
}
|
||||
}
|
||||
|
||||
void tr_torrentStop(tr_torrent* tor)
|
||||
{
|
||||
@@ -741,22 +728,13 @@ void tr_torrentStop(tr_torrent* tor)
|
||||
tor->session->run_in_session_thread([tor]() { tor->stop_now(); });
|
||||
}
|
||||
|
||||
void tr_torrentRemove(
|
||||
tr_torrent* tor,
|
||||
bool delete_flag,
|
||||
tr_torrent_remove_func remove_func,
|
||||
tr_torrent_remove_done_func on_remove_done)
|
||||
void tr_torrentRemove(tr_torrent* tor, bool delete_flag, tr_torrent_remove_func remove_func)
|
||||
{
|
||||
TR_ASSERT(tr_isTorrent(tor));
|
||||
|
||||
tor->is_deleting_ = true;
|
||||
|
||||
tor->session->run_in_session_thread(
|
||||
tr_torrentRemoveInSessionThread,
|
||||
tor,
|
||||
delete_flag,
|
||||
std::move(remove_func),
|
||||
std::move(on_remove_done));
|
||||
tor->session->run_in_session_thread(tr_torrentRemoveInSessionThread, tor, delete_flag, std::move(remove_func));
|
||||
}
|
||||
|
||||
void tr_torrentFreeInSessionThread(tr_torrent* tor)
|
||||
|
||||
@@ -1046,16 +1046,8 @@ private:
|
||||
friend tr_torrent* tr_torrentNew(tr_ctor* ctor, tr_torrent** setme_duplicate_of);
|
||||
friend uint64_t tr_torrentGetBytesLeftToAllocate(tr_torrent const* tor);
|
||||
friend void tr_torrentFreeInSessionThread(tr_torrent* tor);
|
||||
friend void tr_torrentRemoveInSessionThread(
|
||||
tr_torrent* tor,
|
||||
bool delete_flag,
|
||||
tr_torrent_remove_func remove_func,
|
||||
tr_torrent_remove_done_func on_remove_done);
|
||||
friend void tr_torrentRemove(
|
||||
tr_torrent* tor,
|
||||
bool delete_flag,
|
||||
tr_torrent_remove_func remove_func,
|
||||
tr_torrent_remove_done_func on_remove_done);
|
||||
friend void tr_torrentRemoveInSessionThread(tr_torrent* tor, bool delete_flag, tr_torrent_remove_func remove_func);
|
||||
friend void tr_torrentRemove(tr_torrent* tor, bool delete_flag, tr_torrent_remove_func remove_func);
|
||||
friend void tr_torrentSetDownloadDir(tr_torrent* tor, std::string_view path);
|
||||
friend void tr_torrentSetPriority(tr_torrent* tor, tr_priority_t priority);
|
||||
friend void tr_torrentStart(tr_torrent* tor);
|
||||
|
||||
@@ -810,7 +810,6 @@ tr_torrent* tr_torrentNew(tr_ctor* ctor, tr_torrent** setme_duplicate_of);
|
||||
@{ */
|
||||
|
||||
using tr_torrent_remove_func = std::function<bool(std::string_view filename, tr_error* error)>;
|
||||
using tr_torrent_remove_done_func = std::function<void(tr_torrent_id_t, bool success)>;
|
||||
|
||||
/**
|
||||
* @brief Removes our torrent and .resume files for this torrent
|
||||
@@ -820,13 +819,8 @@ using tr_torrent_remove_done_func = std::function<void(tr_torrent_id_t, bool suc
|
||||
* to move to a recycle bin instead of deleting.
|
||||
* The callback is invoked in the session thread and the filename view
|
||||
* is only valid for the duration of the call.
|
||||
* @param on_remove_done A callback to invoke in the session thread when removal is done.
|
||||
*/
|
||||
void tr_torrentRemove(
|
||||
tr_torrent* tor,
|
||||
bool delete_flag,
|
||||
tr_torrent_remove_func remove_func = {},
|
||||
tr_torrent_remove_done_func on_remove_done = {});
|
||||
void tr_torrentRemove(tr_torrent* tor, bool delete_flag, tr_torrent_remove_func remove_func = {});
|
||||
|
||||
/** @brief Start a torrent */
|
||||
void tr_torrentStart(tr_torrent* torrent);
|
||||
|
||||
Reference in New Issue
Block a user