Lars Ingebrigtsen <la...@gnus.org> writes:

> Eric Abrahamsen <e...@ericabrahamsen.net> writes:
>
>> On second thought you're not wrong here: the various *-open-server
>> deffoos report their own failures with `nnheader-report' instead of
>> signaling errors, and then `gnus-open-server' swallows any other errors
>> and converts them to messages.
>
> Ah.  I knew there was something like that somewhere.  :-)
>
>> Failures arrived at via `gnus-request-scan' mostly show up as actual
>> errors.
>
> Perhaps we should adjust those errors to be nnheader-report thingies
> instead?
>
>> - When the gnus-open-server deffoo processes fail, they (or their
>>   downstream functions) signal 'gnus-server-connection-error. (I didn't
>>   go through and do this for every backend, just enough to get the
>>   idea.)
>> - Mail source fetching can fail, in which case 'gnus-mail-source-error
>>   is signaled. nnmail.el no longer handles this error: it propagates up
>>   and out through gnus-request-scan.
>
> I've just skimmed the patch, but the approach looks sound to me (in
> general).
>
>> Some observations and questions:
>>
>> - There are many places and depth-levels in Gnus where failure modes are
>>   dealt with as messages (in effect working like `with-demoted-errors')
>>   or as nil return values from functions, which are then converted into
>>   messages, or sometimes even re-signaled as an actual `error' with a
>>   new message string. This often ends up burying real errors, and/or
>>   making debug on error hard to use. We could try flattening this out:
>>   low-level functions signal errors, and only top-level functions in
>>   gnus-start/gnus-group/gnus-sum get to catch them at the last minute,
>>   and only if necessary (other layers can of course catch and re-signal
>>   the errors if some cleanup work needs to be done). I have no idea if
>>   this would end up working out, but I think it would be good to try.
>>   And more use of `condition-case-unless-debug' at the top level.
>
> I doubt it's possible to find an overarching strategy to handle all
> kinds of errors on the "Gnus" level.  Different errors are, well,
> different.

Yeah, I'm trying to decide if it's worth introducing this new approach
at all. I'd hate to put in something that ends up only being useful in
49% of cases, and now there's yet another system that future code readers
have to make sense of.

I'm also not sure it solves enough problems. For instance, I recently
committed something to nnimap.el that cleans up `nnimap-process-buffers'
when an IMAP connection dies. That happens in like three or four
different places. Ideally a signal handling approach would let us do
that cleanup in a single spot -- either an actual single spot, or a
macro we only have to write once. Kind of a generalization of
`nntp-with-open-group', except it catches any instance of
'gnus-server-error, rather than requiring an explicitly-thrown symbol. I
don't quite see that this is feasible right now.

ANYWAY... I sent a patch suggestion for the mail-source problem in a
separate message. I'm kind of waffling on the rest of this custom error
stuff.

In the meantime I got a backtrace on my stop-the-world nntp connection
error, which I've posted below. I guess there's nothing mysterious about
it -- the process dies (I can't tell if it's actually the timeout doing
it or not), and nntp-accept-process-output/nntp-report ends up raising
the error, and there's nothing up the line to catch it. Does this look
surprising or wrong for any reason?


  (if nntp--report-1 (progn (if nntp-record-commands (progn 
(nntp-record-command "*** CONNECTION LOST ***"))) (throw 
'nntp-with-open-group-error t)) (if nntp-record-commands (progn 
(nntp-record-command "*** CALLED nntp-report ***"))) (nnheader-report 'nntp 
args) (debug) (apply #'error args))
  nntp-report("Server closed connection")
  nntp-accept-process-output(#<process nntpd>)
  nntp-accept-response()
  #f(compiled-function () #<bytecode -0x16437790137177e>)()
  funcall(#f(compiled-function () #<bytecode -0x16437790137177e>))
  (condition-case nil (funcall bodyfun) (quit (if debug-on-quit nil 
(nntp-close-server)) (signal 'quit nil)))
  (setq nntp-with-open-group-internal (condition-case nil (funcall bodyfun) 
(quit (if debug-on-quit nil (nntp-close-server)) (signal 'quit nil))))
  (unwind-protect (setq nntp-with-open-group-internal (condition-case nil 
(funcall bodyfun) (quit (if debug-on-quit nil (nntp-close-server)) (signal 
'quit nil)))) (if timer (progn (cancel-timer timer))))
  (let ((timer (and nntp-connection-timeout (run-at-time 
nntp-connection-timeout nil #'(lambda nil (let* ... ...)))))) (unwind-protect 
(setq nntp-with-open-group-internal (condition-case nil (funcall bodyfun) (quit 
(if debug-on-quit nil (nntp-close-server)) (signal 'quit nil)))) (if timer 
(progn (cancel-timer timer)))) nil)
  (catch 'nntp-with-open-group-error (nntp-possibly-change-group group server 
connectionless) (let ((timer (and nntp-connection-timeout (run-at-time 
nntp-connection-timeout nil #'(lambda nil ...))))) (unwind-protect (setq 
nntp-with-open-group-internal (condition-case nil (funcall bodyfun) (quit (if 
debug-on-quit nil (nntp-close-server)) (signal 'quit nil)))) (if timer (progn 
(cancel-timer timer)))) nil))
  (while (catch 'nntp-with-open-group-error (nntp-possibly-change-group group 
server connectionless) (let ((timer (and nntp-connection-timeout (run-at-time 
nntp-connection-timeout nil #'...)))) (unwind-protect (setq 
nntp-with-open-group-internal (condition-case nil (funcall bodyfun) (quit (if 
debug-on-quit nil ...) (signal ... nil)))) (if timer (progn (cancel-timer 
timer)))) nil)) (setq nntp--report-1 nntp-report-n))
  (let ((nntp-report-n nntp--report-1) (nntp--report-1 t) 
(nntp-with-open-group-internal nil)) (while (catch 'nntp-with-open-group-error 
(nntp-possibly-change-group group server connectionless) (let ((timer (and 
nntp-connection-timeout (run-at-time nntp-connection-timeout nil ...)))) 
(unwind-protect (setq nntp-with-open-group-internal (condition-case nil 
(funcall bodyfun) (quit ... ...))) (if timer (progn (cancel-timer timer)))) 
nil)) (setq nntp--report-1 nntp-report-n)) nntp-with-open-group-internal)
  nntp-with-open-group-function(nil "news.gmane.io" nil #f(compiled-function () 
#<bytecode -0x16437790137177e>))
  nntp-finish-retrieve-group-infos("news.gmane.io" ... 7)
  gnus-finish-retrieve-group-infos((nntp "news.gmane.io") ... 7)
  gnus-read-active-for-groups((nntp "news.gmane.io") ... 7)

Reply via email to