Subject: Re: bug#43682: 28.0.50; Clean up nnimap server buffers?

From: Eric Abrahamsen <[email-masked]>
Date: Wed, 30 Sep 2020 22:09:11 -0700

On 10/01/20 03:30 AM, Lars Ingebrigtsen wrote:
> Eric Abrahamsen <[email-masked]> writes:
>
>> So that's what it's for! That's a mystery solved. It appears that only
>> nntp is asynchronous: at least, it's the only backend that implements
>> `gnus-asynchronous-p'.
>
> Aha.  nnimap should, too.
>
>> nntp.el also contains `nntp-async-{wait,stop-trigger}', but as far as I
>> can tell that has nothing to do with gnus-async.el stuff (?). That's the
>> code that appears to make use of "extra processes per server", and
>> nnimap doesn't have any of that.
>
> Yes, that's a separate thing...
>
>> Not so far as I can tell. sieve.el and sieve-mode.el don't have anything
>> to do with Gnus, and gnus-sieve.el is just about building sieve scripts
>> from Gnus splitting rules. (Now that you mention it, it would be nice if
>> there were a command to edit an IMAP server's sieve scripts from the
>> *Server* buffer.)
>
> Right.  I think there was once some talk about this stuff, but oy vey
> the years...

I'll add it to my own todo list, where it can likewise languish for
years.

>> I'm inclined to delete the alist altogether, but if we keep it at least
>> I can give it a docstring.
>
> No, we should keep it and implement the stuff for gnus-asynchronous-p in
> nnimap, too.

It's possible (I'm not claiming to understand all the code) that all we
would need to do is fix `gnus-async-wait-for-article' to replace its
calls to `nntp-find-connection' and `nntp-accept-process-output' with
something generalized. Those two functions deal with directly with
`nntp-connection-alist', so we'd need something that would do the
equivalent with `nnimap-connection-alist'.

Anyway, in the interest of completing this far less ambitious patch: if
the nnimap connection has timed out, we should remove this connection
from `nnimap-connection-alist', so this version of the patch does that.
If async has opened a second connection, I guess we should leave that
alone, though I don't have too much confidence that the whole process
will recover gracefully from the main connection dying...

Eric

diff --git a/lisp/gnus/nnimap.el b/lisp/gnus/nnimap.el
index d797e893f5..bceba574ca 100644
--- a/lisp/gnus/nnimap.el
+++ b/lisp/gnus/nnimap.el
@@ -407,8 +407,19 @@ nnimap-keepalive
 		      (time-subtract
 		       now
 		       (nnimap-last-command-time nnimap-object))))
-            (ignore-errors              ;E.g. "buffer foo has no process".
-              (nnimap-send-command "NOOP"))))))))
+	    (ignore-errors
+	      (nnimap-send-command "NOOP"))
+	    ;; If our connection has died in the meantime, clean it
+	    ;; and its buffer up.
+	    (unless (memq (process-status (get-buffer-process buffer))
+			  '(open run))
+	      (setq nnimap-process-buffers
+		    (delq buffer nnimap-process-buffers))
+	      (setq nnimap-connection-alist
+		    (seq-filter (lambda (elt)
+				  (null (eq buffer (cdr elt)))
+				  nnimap-connection-alist)))
+	      (kill-buffer buffer))))))))
 
 (defun nnimap-open-connection (buffer)
   ;; Be backwards-compatible -- the earlier value of nnimap-stream was
@@ -1910,6 +1921,10 @@ nnimap-find-connection
 		     '(open run)))
 	  (get-buffer-process (cadr entry))
 	(setq nnimap-connection-alist (delq entry nnimap-connection-alist))
+	(setq nnimap-process-buffers
+	      (delq (cadr entry) nnimap-process-buffers))
+	(when (buffer-live-p (cadr entry))
+	  (kill-buffer (cadr entry)))
 	nil))))
 
 ;; Leave room for `open-network-stream' to issue a couple of IMAP