Commit 327d183b (closing #5571) introduced regressions when a folder
is closing or closed. This patch addresses two problems, one a crasher
and the other a case where the replay queue simply never closed when
requested.
This commit is contained in:
parent
9867509f91
commit
3723a5cdd4
3 changed files with 54 additions and 26 deletions
|
|
@ -474,8 +474,15 @@ private class Geary.ImapEngine.GenericFolder : Geary.AbstractFolder, Geary.Folde
|
|||
debug("Unable to fire semaphore notifying remote folder ready/not ready: %s",
|
||||
notify_err.message);
|
||||
|
||||
remote_folder = null;
|
||||
remote_count = -1;
|
||||
// do this now rather than wait for close_internal_async() to execute to ensure that
|
||||
// any replay operations already queued don't attempt to run
|
||||
try {
|
||||
clear_remote_folder();
|
||||
} catch (Error err) {
|
||||
debug("Unable to clear and signal remote folder due to failed open: %s", err.message);
|
||||
|
||||
// fall through
|
||||
}
|
||||
|
||||
notify_open_failed(Geary.Folder.OpenFailed.REMOTE_FAILED, notify_err);
|
||||
|
||||
|
|
@ -506,11 +513,8 @@ private class Geary.ImapEngine.GenericFolder : Geary.AbstractFolder, Geary.Folde
|
|||
|
||||
// Notify all callers waiting for the remote folder that it's not coming available
|
||||
Imap.Folder? closing_remote_folder = remote_folder;
|
||||
remote_folder = null;
|
||||
remote_count = -1;
|
||||
|
||||
try {
|
||||
remote_semaphore.notify();
|
||||
clear_remote_folder();
|
||||
} catch (Error err) {
|
||||
debug("close_internal_async: Unable to fire remote semaphore: %s", err.message);
|
||||
}
|
||||
|
|
@ -563,6 +567,14 @@ private class Geary.ImapEngine.GenericFolder : Geary.AbstractFolder, Geary.Folde
|
|||
debug("Folder %s closed", to_string());
|
||||
}
|
||||
|
||||
private void clear_remote_folder() throws Error {
|
||||
remote_folder = null;
|
||||
remote_count = -1;
|
||||
|
||||
remote_semaphore.reset();
|
||||
remote_semaphore.notify_result(false, null);
|
||||
}
|
||||
|
||||
private void on_remote_messages_appended(int total) {
|
||||
debug("on_remote_messages_appended: total=%d", total);
|
||||
replay_queue.schedule(new ReplayAppend(this, total));
|
||||
|
|
|
|||
|
|
@ -108,6 +108,13 @@ private class Geary.ImapEngine.ReplayQueue {
|
|||
Logging.debug(Logging.Flag.REPLAY, "[%s] ReplayQueue::closed", to_string());
|
||||
}
|
||||
|
||||
/**
|
||||
* ReplayQueue accepts a NonblockingReportingSemaphore<bool> which, when signaled, returns
|
||||
* true if the remote folder is ready and open, false if not (closing or closed), and
|
||||
* throws an Error if the semaphore has failed. ReplayQueue will wait on this semaphore for
|
||||
* each ReplayOperation waiting to perform a remote operation, cancelling it if the remote
|
||||
* folder is not ready.
|
||||
*/
|
||||
public ReplayQueue(string name, NonblockingReportingSemaphore<bool> remote_reporting_semaphore) {
|
||||
this.name = name;
|
||||
this.remote_reporting_semaphore = remote_reporting_semaphore;
|
||||
|
|
@ -293,21 +300,9 @@ private class Geary.ImapEngine.ReplayQueue {
|
|||
}
|
||||
|
||||
private async void do_replay_remote_async() {
|
||||
try {
|
||||
if (!yield remote_reporting_semaphore.wait_for_result_async()) {
|
||||
debug("Folder %s failed to open, remote replay queue closing", to_string());
|
||||
|
||||
return;
|
||||
}
|
||||
} catch (Error remote_err) {
|
||||
debug("Error for remote queue waiting for remote %s to open, remote queue closing: %s", to_string(),
|
||||
remote_err.message);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
bool queue_running = true;
|
||||
while (queue_running) {
|
||||
// wait for the next operation ... do this *before* waiting for remote
|
||||
ReplayOperation op;
|
||||
try {
|
||||
op = yield remote_queue.recv_async();
|
||||
|
|
@ -318,6 +313,20 @@ private class Geary.ImapEngine.ReplayQueue {
|
|||
break;
|
||||
}
|
||||
|
||||
// wait until the remote folder is opened (or returns false, in which case closed)
|
||||
bool folder_opened = false;
|
||||
try {
|
||||
if (yield remote_reporting_semaphore.wait_for_result_async())
|
||||
folder_opened = true;
|
||||
else
|
||||
debug("Folder %s closed or failed to open, remote replay queue closing", to_string());
|
||||
} catch (Error remote_err) {
|
||||
debug("Error for remote queue waiting for remote %s to open, remote queue closing: %s", to_string(),
|
||||
remote_err.message);
|
||||
|
||||
// fall through
|
||||
}
|
||||
|
||||
if (op is ReplayClose)
|
||||
queue_running = false;
|
||||
|
||||
|
|
@ -325,13 +334,17 @@ private class Geary.ImapEngine.ReplayQueue {
|
|||
|
||||
ReplayOperation.Status status = ReplayOperation.Status.FAILED;
|
||||
Error? remote_err = null;
|
||||
try {
|
||||
status = yield op.replay_remote_async();
|
||||
} catch (Error replay_err) {
|
||||
debug("Replay remote error for %s on %s: %s", op.to_string(), to_string(),
|
||||
replay_err.message);
|
||||
|
||||
remote_err = replay_err;
|
||||
if (folder_opened) {
|
||||
try {
|
||||
status = yield op.replay_remote_async();
|
||||
} catch (Error replay_err) {
|
||||
debug("Replay remote error for %s on %s: %s", op.to_string(), to_string(),
|
||||
replay_err.message);
|
||||
|
||||
remote_err = replay_err;
|
||||
}
|
||||
} else {
|
||||
remote_err = new EngineError.SERVER_UNAVAILABLE("Folder %s not available", to_string());
|
||||
}
|
||||
|
||||
bool has_failed = (status == ReplayOperation.Status.FAILED);
|
||||
|
|
|
|||
|
|
@ -138,6 +138,9 @@ public abstract class Geary.NonblockingAbstractSemaphore {
|
|||
}
|
||||
|
||||
public virtual void reset() {
|
||||
if (!passed)
|
||||
return;
|
||||
|
||||
passed = false;
|
||||
|
||||
notify_at_reset();
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue