From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.io!.POSTED.blaine.gmane.org!not-for-mail From: "J.P." Newsgroups: gmane.emacs.bugs Subject: bug#62044: 30.0.50; ERC 5.5: Auto-reconnect is broken Date: Thu, 09 Mar 2023 06:38:24 -0800 Message-ID: <87lek6kn1b.fsf__2576.28657143272$1678372776$gmane$org@neverwas.me> References: <87wn3rg49m.fsf@gmail.com> <87pm9jy8v7.fsf@neverwas.me> <87sfefr4qa.fsf@gmail.com> <878rg7ql29.fsf@neverwas.me> <87fsaepsso.fsf@neverwas.me> Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="=-=-=" Injection-Info: ciao.gmane.io; posting-host="blaine.gmane.org:116.202.254.214"; logging-data="36530"; mail-complaints-to="usenet@ciao.gmane.io" User-Agent: Gnus/5.13 (Gnus v5.13) Cc: emacs-erc@gnu.org, 62044@debbugs.gnu.org To: xoddf2 Original-X-From: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane-mx.org@gnu.org Thu Mar 09 15:39:27 2023 Return-path: Envelope-to: geb-bug-gnu-emacs@m.gmane-mx.org Original-Received: from lists.gnu.org ([209.51.188.17]) by ciao.gmane.io with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1paHQV-0009G0-0u for geb-bug-gnu-emacs@m.gmane-mx.org; Thu, 09 Mar 2023 15:39:27 +0100 Original-Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1paHQ8-0005vI-NA; Thu, 09 Mar 2023 09:39:04 -0500 Original-Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1paHQ7-0005ut-5z for bug-gnu-emacs@gnu.org; Thu, 09 Mar 2023 09:39:03 -0500 Original-Received: from debbugs.gnu.org ([209.51.188.43]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1paHQ6-0007n3-TF for bug-gnu-emacs@gnu.org; Thu, 09 Mar 2023 09:39:02 -0500 Original-Received: from Debian-debbugs by debbugs.gnu.org with local (Exim 4.84_2) (envelope-from ) id 1paHQ6-0003OG-BY for bug-gnu-emacs@gnu.org; Thu, 09 Mar 2023 09:39:02 -0500 X-Loop: help-debbugs@gnu.org Resent-From: "J.P." Original-Sender: "Debbugs-submit" Resent-CC: bug-gnu-emacs@gnu.org Resent-Date: Thu, 09 Mar 2023 14:39:02 +0000 Resent-Message-ID: Resent-Sender: help-debbugs@gnu.org X-GNU-PR-Message: followup 62044 X-GNU-PR-Package: emacs Original-Received: via spool by 62044-submit@debbugs.gnu.org id=B62044.167837272113005 (code B ref 62044); Thu, 09 Mar 2023 14:39:02 +0000 Original-Received: (at 62044) by debbugs.gnu.org; 9 Mar 2023 14:38:41 +0000 Original-Received: from localhost ([127.0.0.1]:51247 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1paHPk-0003Ng-7c for submit@debbugs.gnu.org; Thu, 09 Mar 2023 09:38:41 -0500 Original-Received: from mail-108-mta224.mxroute.com ([136.175.108.224]:40689) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1paHPh-0003NR-D7 for 62044@debbugs.gnu.org; Thu, 09 Mar 2023 09:38:38 -0500 Original-Received: from mail-111-mta2.mxroute.com ([136.175.111.2] filter006.mxroute.com) (Authenticated sender: mN4UYu2MZsgR) by mail-108-mta224.mxroute.com (ZoneMTA) with ESMTPSA id 186c6cf21c1000edb4.001 for <62044@debbugs.gnu.org> (version=TLSv1/SSLv3 cipher=ECDHE-RSA-AES128-GCM-SHA256); Thu, 09 Mar 2023 14:38:28 +0000 X-Zone-Loop: c946599153481197482309ddb05d37047aa3a4f9a615 X-Originating-IP: [136.175.111.2] DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=neverwas.me ; s=x; h=Content-Type:MIME-Version:Message-ID:Date:References:In-Reply-To: Subject:Cc:To:From:Sender:Reply-To:Content-Transfer-Encoding:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:List-Id:List-Help:List-Unsubscribe:List-Subscribe: List-Post:List-Owner:List-Archive; bh=t1JMivn0tVAjKIoX27fxqe7JoLys5zdFHDjDnQJaJSI=; b=WAO8CVN0M29mwCxRDht1FUMC/o vetFrfl6ksZk0NjchxIjofkVkhPZLb3LBuZVA68ZZHaO/j/yPCO85lNFnxKYeK2o85P4+pVd0AlK7 xYhk5cD2Wc12IkJjs8MJEyarqMXukEUH8KUxIfvtQzwsejg9baVS1Fy+u1fYsrG0ganTX21hGHD4Y jbtpuOLEg/PfajxlebBlYMi9IYMWUTPZtTrij3PX2OXt2xrcyvpGcQjPfbNMCuwG+EibqXRq+gqhX 5q/GVWDQkihjNaR+GeFe7khsDwez/TutXV5gYTGX5bJefMpIpz4Yeg0+uGYbCWppnYlF11lTvsaNT Sy/StzFw==; In-Reply-To: <87fsaepsso.fsf@neverwas.me> (J. P.'s message of "Wed, 08 Mar 2023 18:22:47 -0800") X-Authenticated-Id: masked@neverwas.me X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list X-BeenThere: bug-gnu-emacs@gnu.org List-Id: "Bug reports for GNU Emacs, the Swiss army knife of text editors" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane-mx.org@gnu.org Original-Sender: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane-mx.org@gnu.org Xref: news.gmane.io gmane.emacs.bugs:257615 Archived-At: --=-=-= Content-Type: text/plain "J.P." writes: > I've attached a less sloppy version that probably still fails in some > common cases, but at least it reuses the existing session connector. I've improved upon this further (v3 attached) by adding a housekeeping task to monitor the initial server process from creation. Such a move may be regrettable because it adds yet more complexity to the already dizzying auto-reconnect landscape. However, I couldn't find a suitable way to cover common process errors that aren't presented to the sentinel but still need to engage the reconnect logic. If this leads to a futile game of whack-a-mole, we'll obviously need to try a different approach. But if we do more-or-less build on what I've got so far, we'll definitely need to ensure it agrees with 27 and 28 before spending serious energy on refinement and tests. Thanks. --=-=-= Content-Type: text/x-patch Content-Disposition: attachment; filename=0000-v2-v3.diff >From 7dcccaef52ad4442eabaabe04cd95ffceec048f7 Mon Sep 17 00:00:00 2001 From: "F. Jason Park" Date: Thu, 9 Mar 2023 06:33:38 -0800 Subject: [PATCH 0/1] *** NOT A PATCH *** *** BLURB HERE *** F. Jason Park (1): Add conditional erc-server-reconnect-function lisp/erc/erc-backend.el | 93 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 91 insertions(+), 2 deletions(-) Interdiff: diff --git a/lisp/erc/erc-backend.el b/lisp/erc/erc-backend.el index d289df98bab..1030672506e 100644 --- a/lisp/erc/erc-backend.el +++ b/lisp/erc/erc-backend.el @@ -658,6 +658,31 @@ erc--register-connection (run-hooks 'erc--server-post-connect-hook) (erc-login)) +(defvar erc--server-connect-function #'erc--server-propagate-failed-connection + "Function called one second after creating a server process. +Called with the newly created process just before the opening IRC +protocol exchange.") + +(defun erc--server-propagate-failed-connection (process) + "Ensure the PROCESS sentinel runs at least once on early failure. +Act as a watchdog timer to force `erc-process-sentinel' and its +finalizers, like `erc-disconnected-hook', to run when PROCESS has +a status of `failed' after one second. Print the +`process-exit-status', which can be a number, like 111, or a +message, like \"TLS negotiation failed\"." + (when (eq (process-status process) 'failed) + (erc-display-message + nil 'error (process-buffer process) + (format "Process exit status: %S" (process-exit-status process))) + (pcase (process-exit-status process) + ((guard erc--server-reconnect-timer)) + (111 + (delete-process process)) + (`(file-error ,(rx "failed") ,(rx "unreachable") . ,_) + (erc-process-sentinel process "failed with code -523\n")) + ((rx "tls" (+ nonl) "failed") + (erc-process-sentinel process "failed with code -525\n"))))) + (defvar erc--server-connect-dumb-ipv6-regexp ;; Not for validation (gives false positives). (rx bot "[" (group (+ (any xdigit digit ":.")) (? "%" (+ alnum))) "]" eot)) @@ -708,9 +733,11 @@ erc-server-connect (with-current-buffer buffer (erc-current-nick)))) ;; wait with script loading until we receive a confirmation (first ;; MOTD line) - (if (eq (process-status process) 'connect) + (if (process-contact process :nowait) ;; waiting for a non-blocking connect - keep the user informed - (erc-display-message nil nil buffer "Opening connection..\n") + (progn + (erc-display-message nil nil buffer "Opening connection..\n") + (run-at-time 1 nil erc--server-connect-function process)) (message "%s...done" msg) (erc--register-connection)))) @@ -759,9 +786,9 @@ erc-server-delayed-check-reconnect 2))) (let ((reschedule (lambda (proc) - (let ((erc-server-reconnect-timeout - erc--server-reconnect-timeout)) - (with-current-buffer buffer + (with-current-buffer buffer + (let ((erc-server-reconnect-timeout + erc--server-reconnect-timeout)) (delete-process proc) (erc-display-message nil 'error buffer "Nobody home...") (erc-schedule-reconnect buffer 0)))))) @@ -770,18 +797,22 @@ erc-server-delayed-check-reconnect "*erc-connectivity-check" nil erc-session-server erc-session-port :nowait t)) - tls-check) - (when (and (not (eq erc-session-connector - #'erc-open-network-stream)) - (process-contact proc :tls-parameters)) - (setq tls-check - (run-at-time - 1 1 (lambda (proc) - (unless (eq 'connect (process-status proc)) - (cancel-timer tls-check)) - (when (eq 'failed (process-status proc)) - (funcall reschedule proc))) - proc))) + (check-expire (time-add 10 (current-time))) + check-aside) + (setq check-aside + (run-at-time + 1 1 (lambda (proc) + (when (or (not (eq 'connect (process-status proc))) + (time-less-p check-expire (current-time))) + (cancel-timer check-aside)) + (when (time-less-p check-expire (current-time)) + (erc-display-message + nil 'error buffer "Timed out waiting on `connect'") + (delete-process proc) + (funcall reschedule proc)) + (when (eq 'failed (process-status proc)) + (funcall reschedule proc))) + proc)) (set-process-filter proc (lambda (proc _) (delete-process proc) @@ -790,14 +821,16 @@ erc-server-delayed-check-reconnect (run-at-time nil nil #'erc-server-delayed-reconnect buffer))) (set-process-sentinel - proc (lambda (cproc event) + proc (lambda (proc event) (with-current-buffer buffer (pcase event ("open\n" - (run-at-time nil nil #'send-string - cproc "PING *connect-check*\r\n")) - ("connection broken by remote peer\n" - (funcall reschedule cproc))))))) + (run-at-time + nil nil #'send-string proc + (format "PING %d\r\n" (time-convert nil 'integer)))) + ((or "connection broken by remote peer\n" + (rx bot "failed")) + (funcall reschedule proc))))))) (file-error (funcall reschedule nil)))))) (defun erc-server-filter-function (process string) -- 2.39.2 --=-=-= Content-Type: text/x-patch Content-Disposition: attachment; filename=0001-Add-conditional-erc-server-reconnect-function.patch >From 7dcccaef52ad4442eabaabe04cd95ffceec048f7 Mon Sep 17 00:00:00 2001 From: "F. Jason Park" Date: Wed, 8 Mar 2023 06:14:36 -0800 Subject: [PATCH 1/1] Add conditional erc-server-reconnect-function * lisp/erc/erc-backend.el (erc--server-reconnect-timer, erc-server-delayed-check-reconnect): Add possible alternate value for option `erc-server-reconnect-function' that only attempts to reconnect after hearing back from the server. Also add helper variable. (erc-server-connect): Run erc--server-connect-function for async processes. (erc--server-connect-function, erc--server-propagate-failed-connection): Add connect-function variable and default value to run on process creation and execute process-failure handlers. --- lisp/erc/erc-backend.el | 93 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 91 insertions(+), 2 deletions(-) diff --git a/lisp/erc/erc-backend.el b/lisp/erc/erc-backend.el index 567443f5329..1030672506e 100644 --- a/lisp/erc/erc-backend.el +++ b/lisp/erc/erc-backend.el @@ -658,6 +658,31 @@ erc--register-connection (run-hooks 'erc--server-post-connect-hook) (erc-login)) +(defvar erc--server-connect-function #'erc--server-propagate-failed-connection + "Function called one second after creating a server process. +Called with the newly created process just before the opening IRC +protocol exchange.") + +(defun erc--server-propagate-failed-connection (process) + "Ensure the PROCESS sentinel runs at least once on early failure. +Act as a watchdog timer to force `erc-process-sentinel' and its +finalizers, like `erc-disconnected-hook', to run when PROCESS has +a status of `failed' after one second. Print the +`process-exit-status', which can be a number, like 111, or a +message, like \"TLS negotiation failed\"." + (when (eq (process-status process) 'failed) + (erc-display-message + nil 'error (process-buffer process) + (format "Process exit status: %S" (process-exit-status process))) + (pcase (process-exit-status process) + ((guard erc--server-reconnect-timer)) + (111 + (delete-process process)) + (`(file-error ,(rx "failed") ,(rx "unreachable") . ,_) + (erc-process-sentinel process "failed with code -523\n")) + ((rx "tls" (+ nonl) "failed") + (erc-process-sentinel process "failed with code -525\n"))))) + (defvar erc--server-connect-dumb-ipv6-regexp ;; Not for validation (gives false positives). (rx bot "[" (group (+ (any xdigit digit ":.")) (? "%" (+ alnum))) "]" eot)) @@ -708,9 +733,11 @@ erc-server-connect (with-current-buffer buffer (erc-current-nick)))) ;; wait with script loading until we receive a confirmation (first ;; MOTD line) - (if (eq (process-status process) 'connect) + (if (process-contact process :nowait) ;; waiting for a non-blocking connect - keep the user informed - (erc-display-message nil nil buffer "Opening connection..\n") + (progn + (erc-display-message nil nil buffer "Opening connection..\n") + (run-at-time 1 nil erc--server-connect-function process)) (message "%s...done" msg) (erc--register-connection)))) @@ -744,6 +771,68 @@ erc-server-delayed-reconnect (with-current-buffer buffer (erc-server-reconnect)))) +(defvar-local erc--server-reconnect-timeout nil) + +(defun erc-server-delayed-check-reconnect (buffer) + "Wait for internet connectivity before trying to reconnect. +BUFFER is the server buffer for the current connection." + ;; This may appear to hang for a good while at various places + ;; because it calls wait_reading_process_output a bunch. It does at + ;; least sometimes print "Waiting for socket from ..." or similar. + (with-current-buffer buffer + (setq erc--server-reconnect-timeout + (min 300 (* (or erc--server-reconnect-timeout + erc-server-reconnect-timeout) + 2))) + (let ((reschedule + (lambda (proc) + (with-current-buffer buffer + (let ((erc-server-reconnect-timeout + erc--server-reconnect-timeout)) + (delete-process proc) + (erc-display-message nil 'error buffer "Nobody home...") + (erc-schedule-reconnect buffer 0)))))) + (condition-case _ + (let ((proc (funcall erc-session-connector + "*erc-connectivity-check" nil + erc-session-server erc-session-port + :nowait t)) + (check-expire (time-add 10 (current-time))) + check-aside) + (setq check-aside + (run-at-time + 1 1 (lambda (proc) + (when (or (not (eq 'connect (process-status proc))) + (time-less-p check-expire (current-time))) + (cancel-timer check-aside)) + (when (time-less-p check-expire (current-time)) + (erc-display-message + nil 'error buffer "Timed out waiting on `connect'") + (delete-process proc) + (funcall reschedule proc)) + (when (eq 'failed (process-status proc)) + (funcall reschedule proc))) + proc)) + (set-process-filter + proc (lambda (proc _) + (delete-process proc) + (with-current-buffer buffer + (setq erc--server-reconnect-timeout nil)) + (run-at-time nil nil #'erc-server-delayed-reconnect + buffer))) + (set-process-sentinel + proc (lambda (proc event) + (with-current-buffer buffer + (pcase event + ("open\n" + (run-at-time + nil nil #'send-string proc + (format "PING %d\r\n" (time-convert nil 'integer)))) + ((or "connection broken by remote peer\n" + (rx bot "failed")) + (funcall reschedule proc))))))) + (file-error (funcall reschedule nil)))))) + (defun erc-server-filter-function (process string) "The process filter for the ERC server." (with-current-buffer (process-buffer process) -- 2.39.2 --=-=-=--