New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
RT hangs when files in the file browser tab change or get deleted, or when batch processing #3289
Comments
Cannot reproduce with debug and release builds of the latest master on Debian Stretch AMD64 (multi-core machine). Could you please provide more information and have a look at "How to write useful bug reports"? For example you completely omitted your OS or features (found in your PP3s) you have activated for your RAWs. Does it always happen or only with certain RAWs? Have you checked that your storage medium (HD/SSD/network) still performs as expected when reading/writing files? Are you sure there is no other process hammering it? Question upon question ... ;) |
@da-phil ping. |
Sorry for the late reply!
And this is my RT config (~/config/RawTherapee/options) This behavior is completely independent of RAW developing features, it also happens when I don't use any features, not even colour profiles, as I said it also happens when the folder which is opened in the RT file browser changes (files were added or deleted). |
Wild shot: what if you delete (or rename) your options file, then run RT, this will create a new options file, then create an empty folder
Did that make any difference? |
Unfortunately it didn't, thanks for the idea though! |
And this only happens in RT, or also in other GTK based programs? I only ask, because in the past I had some problems (hangs) with Silly question: Your RT was compiled with OpenMP enabled? |
I killed all gvfs services and tried again, but unfortunately it also wasn't a gvfs backend :(
I also tried it with a debug build, but had the same problem. |
@da-phil When batch processing, is the source folder the same as destination folder or is it a different folder? |
@da-phil Maybe you could use |
@heckflosse jup, it's the same folder. |
Does rt hang also when destination is different to source? |
@heckflosse when I save to another folder RT doesn't hang. |
@da-phil Saving to source folder is a known issue for rt. rt periodically checks the source folder for new files afaik. This can cause the behaviour you detected (hangs or freezes). It's an Issue we (rt) have to solve. Meanwhile you can work around it saving to a different folder. |
ah, I see, I didn't know it was a known problem, I was pretty sure some months ago I didn't have that problem, RT was responsive at all times. the amount of syscalls happening on my machine is incredible, I checked other software too, even in idle mode there are so many syscalls appearing. |
I just realized that this problem was not noticeable when I worked in a fairly small folder with maybe 30 RAW and JPG files, however when I work in a folder with hundreds of RAW and JPG files I notice the lag while RT scans for new files and creates new thumbnails. looks like this implementation might need a tweak or a different method. from working with events and fileIO blocking calls (select(), poll() and the likes) myself I imagine having a blocking call in a separate thread which waits for incoming events in the filesystem and hence triggers updates in the RT file browser without even blocking the GUI. but before talking bullsh*t, I probably should have a look at the code first myself ;) |
@da-phil 'I probably should have a look at the code first myself ;)' That is a great idea!!!!! |
@heckflosse I saw that there is stuff like inotify or dnotify for Linux, however there even seems to be an OS agnostic way in GTK with the GFileMonitor functions. I assume GTK has an underlying OS specific implementation for each supported OS. |
@da-phil I would really appreciate if you can take a look at this issue. I'm a specialist for speedups but not for the other stuff!!! I can at least help to test a solution on Win64 and Linux64 Ingo |
I'm so busy recently I might not be able to do it, I should rather process a lot of pictures with RT instead of hacking it :D |
@heckflosse So it seems that the FileMonitor callback gets called after an event (file created / deleted / changed) and calls Anybody an idea how to move |
@heckflosse I think, you remembered #3318, but that is unfortunately not related to this very problem. I'm still no GUI expert at all, but I'll have a look at the code. I suppose, it's not that critical in terms of time... |
@heckflosse @Floessie this "flaw" is still valid, at least in |
@da-phil @heckflosse Okay, here is my first take (patch against current master): diff --git a/rtgui/filecatalog.cc b/rtgui/filecatalog.cc
index 3ed7608..98df5d6 100644
--- a/rtgui/filecatalog.cc
+++ b/rtgui/filecatalog.cc
@@ -51,7 +51,9 @@ FileCatalog::FileCatalog (CoarsePanel* cp, ToolBar* tb, FilePanel* filepanel) :
previewsToLoad(0),
previewsLoaded(0),
coarsePanel(cp),
- toolBar(tb)
+ toolBar(tb),
+ do_reparse_directory_pending(false),
+ do_reparse_directory_expected_counter(0)
{
inTabMode = false;
@@ -1697,7 +1699,6 @@ void FileCatalog::filterChanged ()
void FileCatalog::reparseDirectory ()
{
-
if (selectedDirectory.empty()) {
return;
}
@@ -1707,44 +1708,9 @@ void FileCatalog::reparseDirectory ()
return;
}
- std::vector<Glib::ustring> nfileNameList = getFileList ();
-
- // check if a thumbnailed file has been deleted
- const std::vector<ThumbBrowserEntryBase*>& t = fileBrowser->getEntries ();
- std::vector<Glib::ustring> fileNamesToDel;
-
- for (size_t i = 0; i < t.size(); i++)
- if (!Glib::file_test (t[i]->filename, Glib::FILE_TEST_EXISTS)) {
- fileNamesToDel.push_back (t[i]->filename);
- }
-
- for (size_t i = 0; i < fileNamesToDel.size(); i++) {
- delete fileBrowser->delEntry (fileNamesToDel[i]);
- cacheMgr->deleteEntry (fileNamesToDel[i]);
- previewsLoaded--;
- }
-
- if (!fileNamesToDel.empty ()) {
- _refreshProgressBar();
- }
-
- // check if a new file has been added
- for (size_t i = 0; i < nfileNameList.size(); i++) {
- bool found = false;
-
- for (size_t j = 0; j < fileNameList.size(); j++)
- if (nfileNameList[i] == fileNameList[j]) {
- found = true;
- break;
- }
-
- if (!found) {
- checkAndAddFile (Gio::File::create_for_parse_name (nfileNameList[i]));
- _refreshProgressBar ();
- }
+ if (!do_reparse_directory_pending.exchange(true)) {
+ Glib::signal_timeout().connect_once(sigc::bind(sigc::mem_fun(*this, &FileCatalog::doReparseDirectory), ++do_reparse_directory_expected_counter), 500);
}
-
- fileNameList = nfileNameList;
}
#ifdef WIN32
@@ -1939,6 +1905,7 @@ void FileCatalog::setFilterPanel (FilterPanel* fpanel)
filterPanel->set_sensitive (false);
filterPanel->setFilterPanelListener (this);
}
+
void FileCatalog::trashChanged ()
{
if (trashIsEmpty()) {
@@ -1948,6 +1915,56 @@ void FileCatalog::trashChanged ()
}
}
+void FileCatalog::doReparseDirectory(unsigned long expected_counter)
+{
+ if (expected_counter != do_reparse_directory_expected_counter) {
+ return;
+ }
+
+ do_reparse_directory_pending = false;
+
+ std::vector<Glib::ustring> nfileNameList = getFileList ();
+
+ // check if a thumbnailed file has been deleted
+ const std::vector<ThumbBrowserEntryBase*>& t = fileBrowser->getEntries ();
+ std::vector<Glib::ustring> fileNamesToDel;
+
+ for (size_t i = 0; i < t.size(); i++)
+ if (!Glib::file_test (t[i]->filename, Glib::FILE_TEST_EXISTS)) {
+ fileNamesToDel.push_back (t[i]->filename);
+ }
+
+ for (size_t i = 0; i < fileNamesToDel.size(); i++) {
+ delete fileBrowser->delEntry (fileNamesToDel[i]);
+ cacheMgr->deleteEntry (fileNamesToDel[i]);
+ previewsLoaded--;
+ //Gtk::Main::iteration(false);
+ }
+
+ if (!fileNamesToDel.empty ()) {
+ _refreshProgressBar();
+ }
+
+ // check if a new file has been added
+ for (size_t i = 0; i < nfileNameList.size(); i++) {
+ bool found = false;
+
+ for (size_t j = 0; j < fileNameList.size(); j++)
+ if (nfileNameList[i] == fileNameList[j]) {
+ found = true;
+ break;
+ }
+
+ if (!found) {
+ checkAndAddFile (Gio::File::create_for_parse_name (nfileNameList[i]));
+ _refreshProgressBar ();
+ //Gtk::Main::iteration(false);
+ }
+ }
+
+ fileNameList = nfileNameList;
+}
+
// Called within GTK UI thread
void FileCatalog::buttonQueryClearPressed ()
{
diff --git a/rtgui/filecatalog.h b/rtgui/filecatalog.h
index b7ea180..ea190ed 100644
--- a/rtgui/filecatalog.h
+++ b/rtgui/filecatalog.h
@@ -19,6 +19,9 @@
#ifndef _FILECATALOG_
#define _FILECATALOG_
+#include <set>
+#include <atomic>
+
#ifdef WIN32
#include "windirmonitor.h"
#endif
@@ -26,7 +29,6 @@
#include "exiffiltersettings.h"
#include <giomm.h>
#include "fileselectionlistener.h"
-#include <set>
#include "fileselectionchangelistener.h"
#include "coarsepanel.h"
#include "toolbar.h"
@@ -148,11 +150,13 @@ private:
int previewsToLoad;
int previewsLoaded;
-
std::vector<Glib::ustring> fileNameList;
std::set<Glib::ustring> editedFiles;
guint modifierKey; // any modifiers held when rank button was pressed
+ std::atomic<bool> do_reparse_directory_pending;
+ std::atomic<unsigned long> do_reparse_directory_expected_counter;
+
#ifndef _WIN32
Glib::RefPtr<Gio::FileMonitor> dirMonitor;
#else
@@ -164,6 +168,7 @@ private:
std::vector<Glib::ustring> getFileList ();
BrowserFilter getFilter ();
void trashChanged ();
+ void doReparseDirectory(unsigned long expected_counter);
public:
// thumbnail browsers
@@ -254,7 +259,7 @@ public:
void runFilterDialog ();
void on_realize();
- void reparseDirectory ();
+ void reparseDirectory();
void _openImage (std::vector<Thumbnail*> tmb);
void zoomIn (); The idea is, to accumulate calls to |
Thank you @Floessie! I still wonder whether |
@da-phil |
Ah, I didn't fully realise that this was another issue with Something like that: class FileCatalog {
....
public:
void stopReparseThread();
private:
std::atomic<bool> stop_reparse;
std::mutex mutex_blk;
std::condition_variable cond_reparse;
...
};
FileCatalog::FileCatalog(...)
{
....
stop_reparse = false;
....
}
void FileCatalog::reparseDirectory()
{
....
cond_reparse.notify_all();
}
void FileCatalog::doReparseDirectory()
{
std::lock_guard<std::mutex> lock(mutex_blk);
while(!stop_reparse)
{
cond_reparse.wait(lock); // block here
// do the reparsing here
}
}
void FileCatalog::stopReparseThread()
{
stop_reparse = true;
cond_reparse.notify_all();
}
int main(...)
{
...
std::thread reparseDirectory_thread(&FileCatalog::doReparseDirectory, &filecatalog, &received_signal);
...
// shutting down thread
filecatalog.stopReparseThread();
reparseDirectory_thread.join();
...
} It's really just putting a thought together in a quick & dirty hack, I don't have any idea how to do it in the glib/gtk framework. |
@da-phil In principle that's feasible. But as always: The devil is in the details. ;) If you come up with an implementation, we will all rejoice and the honor will be yours. Be careful when interacting with the UI thread. But first measure, if you are on the right track. I'd start the thread joinable in |
@Floessie Unfortunately your patch didn't fix the issue, but it might have made things faster. |
@da-phil Great! 👍 We can use your help and contribution! |
@da-phil Did some research to help you with your implementation:
All told, this really seems to be doable, and you seem to have the skills to do so. 👍 If you get stuck, we will help, of course. Patches are okay, but if you expect several review iterations you might be better off forking here on GitHub so that we can easily test your branch. This is also better on the long run, if you like to contribute every now and then. HTH and good luck |
@Floessie Wow, thanks for your insightful help, with those hints it will be much easier for sure! It would have taken me ages to find out about the thread-safeness of all those components! :o |
@da-phil You're welcome. Same with me: I'm also working more with than on RT. :) |
@da-phil can you still reproduce this? |
Still valid? Or can we close? |
I just saved a HDR DNG from HDRMerge into a folder which I had open in RT's File Browser, and RT crashed. |
I couldn't test the new code on a folder with thousands of pictures yet, but what I noticed now is, that newly saved files don't appear in the file-browser, only after you hit the 'refresh' button. In my opinion this is also not a desirable behaviour, although the hanging GUI seems not to be a problem anymore. |
@da-phil can you reproduce the freeze in 5.5(rc*)? |
@Beep6581 no, now I can't reproduce the error anymore, this is great, thanks to everybody who was involved in fixing it! However, now I have to hit the refresh button in the filebrowser for the newly exported file(s) to appear in the filebrowser. I've been testing with the latest version from dev.
|
I'm using the latest commit on master
Recently I noticed that RT hangs while files in the directory which is shown in the file browser tab change (when image is saved after editing) or get deleted. sometimes RT hangs for several seconds until the file browser keeps up with the changes.
RT also becomes completely unresponsive when batch processing pictures, I always have to wait until all files are processed before I can do anything with the GUI again.
The text was updated successfully, but these errors were encountered: