atom feed9 messages in net.sourceforge.lists.courier-coneRe: [cone] Automatic Refresh for loca...
FromSent OnAttachments
Linux-FanDec 30, 2016 2:53 pm.txt
Sam VarshavchikDec 31, 2016 7:23 am 
Linux-FanDec 31, 2016 7:57 am 
Sam VarshavchikDec 31, 2016 9:27 am 
Linux-FanJan 1, 2017 2:15 pm 
Linux-FanFeb 1, 2017 1:42 pm.diff
Sam VarshavchikFeb 1, 2017 6:44 pm 
Linux-FanFeb 2, 2017 8:25 am.diff
Sam VarshavchikFeb 3, 2017 3:58 am 
Subject:Re: [cone] Automatic Refresh for local Maildir's mail counts
From:Linux-Fan (Ma_S@web.de)
Date:Feb 1, 2017 1:42:04 pm
List:net.sourceforge.lists.courier-cone
Attachments:

[Sun, 1 Jan 2017 23:15:02 +0100] Linux-Fan <Ma_S@web.de> wrote:

[Sat, 31 Dec 2016 12:27:38 -0500] Sam Varshavchik <mrs@courier-mta.com> wrote:

Linux-Fan writes:

[...]

Is it possible/planned to add a means of updating the message counts from the folder hierarchy view automatically as well (similar to what I did upon receiving a SIGUSR1 for my proof-of-concept patch from the previous mail)?

I'm open to such a feature; however this approach won't work. Signals

[...]

The only safe way to do this: in addition to installing a signal handler, an internal pipe needs to be created, and put into nonblocking mode. The only thing the signal handler does is write a byte to the pipe, ignoring the results, and immediately terminating.

Then, on the folder screen only, in addition to handling all the regular events the read end of the pipe gets polled as well, and when something is read, what your patch does would happen.

OK. I am going to check this out when I find time to dig into the source code again :)

[...]

I have taken on the challenge and tried to create a (more) correct patch which enables cone-0.92 to update all folder's message counts upon receiving a SIGUSR1.

It is not using a pipe, but a C++11 std::atomic instead. If that cannot be used, because Cone needs to compile without C++11 (I used `./configure CPPFLAGS=-std=c++11` to get it to work), I'd replace this by a variable which is marked `volatile sig_atomic_t`.

What do you think? Does it make sense to put it that way or have I misplaced the call to `processHierharcyRefresh()`? Is it better to use `SA_RESTART` or not? I am not quite sure... Also, in order to improve the folder refreshing mechanism, I have implemented a `RefreshIterator` which uses `updateInfo` on all folder entries. Have I used the API correctly?

Even with that, things may not work 100%. All the code needs to be audited and verified that it'll correctly handle an interrupted system call.

Correct signal handling is hard.

Yes it is :( Especially signal handling from within multithreaded applications is probably asking for trouble, so I understand that might not be the best solution here...

If signal handling is still too much of an issue with regard to the overall application stability, might it make sense to replace my check for `pendingUpdates.exchange(0) > 0` with a simple timer (like if now - lastTimeOfCheck > NN seconds refresh)?

By the way: If you wonder about the `masysma` prefixes and annotations: I will happily remove these if the patch has a chance of being incorporated but for now I have added them to easily navigate to my modifications within the code and make sure I do not confuse my changes with what was already there...

Yours Sincerely and TIA Linux-Fan

-- http://masysma.lima-city.de/

diff -Nau -x Makefile.in -x Makefile -x .deps -x '*.cache' -x buildversion.H -x
'*.log' -x config.status -r cone-0.92/cone/cone.C cone-0.92_new/cone/cone.C --- cone-0.92/cone/cone.C 2015-02-28 14:20:13.000000000 +0100 +++ cone-0.92_new/cone/cone.C 2017-02-01 21:19:07.334905194 +0100 @@ -58,6 +58,8 @@ #include "macros.H" #include "configscreen.H"

+#include "masysmarefreshsignal.H" // MASYSMA CHANGED + #include <iostream>

using namespace std; @@ -429,6 +431,7 @@ myServer **selectedServer) { CursesHierarchy hierarchy_screen( &myServer::hierarchy, mainScreen); + MasysmaRefreshSignal::setHierarchyPointer(&hierarchy_screen);

titleBar->setTitles(_("FOLDERS"), "");

@@ -474,6 +477,8 @@ *selectedFolder=hierarchy_screen.folderSelected; if (selectedServer) *selectedServer=hierarchy_screen.serverSelected; + + MasysmaRefreshSignal::setHierarchyPointer(NULL); }

void hierarchyScreen(void *dummy) @@ -1185,6 +1190,7 @@ }

signal(SIGPIPE, SIG_IGN); + MasysmaRefreshSignal::registerSignalHandler(); // MASYSMA CHANGED macroPtr= &macroBuffer; init(); // Common initialization between cone and leaf.

diff -Nau -x Makefile.in -x Makefile -x .deps -x '*.cache' -x buildversion.H -x
'*.log' -x config.status -r cone-0.92/cone/curseshierarchy.C
cone-0.92_new/cone/curseshierarchy.C --- cone-0.92/cone/curseshierarchy.C 2014-01-06 20:51:56.000000000 +0100 +++ cone-0.92_new/cone/curseshierarchy.C 2017-02-01 22:17:23.825889157 +0100 @@ -985,6 +985,28 @@ me->processDeletedFolder(parent, deleted, updatedFolder); }

+// BEGIN MASYSMA CHANGED CODE +bool CursesHierarchy::MasysmaRefreshIterator::visit(Hierarchy::Folder* f) +{ + if(f != NULL && this->cs != NULL) + f->updateInfo(this->cs, true); + return true; +} + +bool CursesHierarchy::MasysmaRefreshIterator::visit(Hierarchy::Server* s) +{ + if(s != NULL) + this->cs = s->getServer(); + return true; +} + +void CursesHierarchy::masysmaRefreshAllFolders() +{ + MasysmaRefreshIterator iterator; + getHierarchy()->root.prefixIterate(iterator); +} +// END MASYSMA CHANGED CODE + /////////// bool CursesHierarchy::processKey(const Curses::Key &key) { diff -Nau -x Makefile.in -x Makefile -x .deps -x '*.cache' -x buildversion.H -x
'*.log' -x config.status -r cone-0.92/cone/curseshierarchy.H
cone-0.92_new/cone/curseshierarchy.H --- cone-0.92/cone/curseshierarchy.H 2014-01-06 20:51:56.000000000 +0100 +++ cone-0.92_new/cone/curseshierarchy.H 2017-02-01 22:10:43.324152755 +0100 @@ -61,6 +61,16 @@

};

+ // BEGIN MASYSMA CHANGED + class MasysmaRefreshIterator: public Hierarchy::EntryIterator { + private: + myServer* cs = NULL; + public: + bool visit(Hierarchy::Folder* f); + bool visit(Hierarchy::Server* s); + }; + // END MASYSMA CHANGED + public: friend class DrawIterator;

@@ -122,6 +132,11 @@ public: void processDeletedFolder(Hierarchy::Folder *, Hierarchy::Folder *, const mail::folder *); + +// BEGIN MASYSMA CHANGED CODE + void masysmaRefreshAllFolders(); +// END MASYSMA CHANGED CODE + };

#endif diff -Nau -x Makefile.in -x Makefile -x .deps -x '*.cache' -x buildversion.H -x
'*.log' -x config.status -r cone-0.92/cone/Makefile.am
cone-0.92_new/cone/Makefile.am --- cone-0.92/cone/Makefile.am 2015-02-28 17:03:16.000000000 +0100 +++ cone-0.92_new/cone/Makefile.am 2017-02-01 20:16:17.879100122 +0100 @@ -81,7 +81,8 @@ spellchecker.H \ spellcheckerbase.C spellcheckerbase.H \ tags.C tags.H \ - typeahead.C typeahead.H + typeahead.C typeahead.H \ + masysmarefreshsignal.C masysmarefreshsignal.H # MASYSMA CHANGED

leaf_SOURCES=\ curseseditmessage.C \ diff -Nau -x Makefile.in -x Makefile -x .deps -x '*.cache' -x buildversion.H -x
'*.log' -x config.status -r cone-0.92/cone/masysmarefreshsignal.C
cone-0.92_new/cone/masysmarefreshsignal.C --- cone-0.92/cone/masysmarefreshsignal.C 1970-01-01 01:00:00.000000000 +0100 +++ cone-0.92_new/cone/masysmarefreshsignal.C 2017-02-01 21:28:43.533566363
+0100 @@ -0,0 +1,50 @@ +// BEGIN MASYSMA CHANGED + +#include "masysmarefreshsignal.H" +#include <atomic> +#include <signal.h> + +CursesHierarchy* MasysmaRefreshSignal::masysmaHptr = NULL; + +// Signal handling related stuff is written in C instead of C++ as to keep +// the function as simple as possible and leave as little potential for +// interferences as possible. +static std::atomic_int pendingUpdates(0); +static void masysmaReceiveRefreshSignal(int arg0) +{ + pendingUpdates++; +} + +void MasysmaRefreshSignal::registerSignalHandler() +{ + struct sigaction act; + struct sigaction oact; // original action, ignored for now... + act.sa_handler = &masysmaReceiveRefreshSignal; + sigemptyset(&act.sa_mask); + act.sa_flags = + // Restart running calls instead of returning EINTR. + // TODO: Is this behaviour wanted? + SA_RESTART | + // Simple signal handler function form + SA_SIGINFO ; + sigaction(SIGUSR1, &act, &oact); +} + +void MasysmaRefreshSignal::setHierarchyPointer(CursesHierarchy* hptr) +{ + MasysmaRefreshSignal::masysmaHptr = hptr; +} + +void MasysmaRefreshSignal::processHierarchyRefresh() +{ + // If the previous value before setting pendingUpdates to 0 was > 0 + // and we are on the correct screen, we register a refresh. + // This means a signal received while not on the hierarchy screen is + // dropped. An alternative sematics enabling refreshing after returning + // to the hierarchy screen may be achieved by changing the order of + // operands for &&. + if(pendingUpdates.exchange(0) > 0 && masysmaHptr != NULL) + MasysmaRefreshSignal::masysmaHptr->masysmaRefreshAllFolders(); +} + +// END MASYSMA CHANGED diff -Nau -x Makefile.in -x Makefile -x .deps -x '*.cache' -x buildversion.H -x
'*.log' -x config.status -r cone-0.92/cone/masysmarefreshsignal.H
cone-0.92_new/cone/masysmarefreshsignal.H --- cone-0.92/cone/masysmarefreshsignal.H 1970-01-01 01:00:00.000000000 +0100 +++ cone-0.92_new/cone/masysmarefreshsignal.H 2017-02-01 21:23:23.114216608
+0100 @@ -0,0 +1,14 @@ +#pragma once +// BEGIN MASYSMA CHANGED +#include "curseshierarchy.H" + +class MasysmaRefreshSignal { +private: + static CursesHierarchy* masysmaHptr; +public: + static void registerSignalHandler(); + static void setHierarchyPointer(CursesHierarchy* hptr); + static void processHierarchyRefresh(); +}; + +// END MASYSMA CHANGED diff -Nau -x Makefile.in -x Makefile -x .deps -x '*.cache' -x buildversion.H -x
'*.log' -x config.status -r cone-0.92/cone/myserver.C
cone-0.92_new/cone/myserver.C --- cone-0.92/cone/myserver.C 2014-01-06 20:51:56.000000000 +0100 +++ cone-0.92_new/cone/myserver.C 2017-02-01 21:18:47.854965089 +0100 @@ -18,6 +18,7 @@ #include "curses/cursesstatusbar.H" #include "libmail/misc.H" #include "gettext.H" +#include "masysmarefreshsignal.H" // MASYSMA CHANGED #include <time.h> #include <errno.h> #include <fcntl.h> @@ -281,6 +282,8 @@ break; } } + + MasysmaRefreshSignal::processHierarchyRefresh(); // MASYSMA CHANGED }

statusBar->notbusy();

------------------------------------------------------------------------------ Check out the vibrant tech community on one of the world's most engaging tech sites, SlashDot.org! http://sdm.link/slashdot