unofficial mirror of bug-gnu-emacs@gnu.org 
 help / color / mirror / code / Atom feed
From: Lars Ingebrigtsen <larsi@gnus.org>
To: Eli Zaretskii <eliz@gnu.org>
Cc: 22493@debbugs.gnu.org
Subject: bug#22493: 25.1.50; open-gnutls-stream doesn't respect :nowait, so the connections are synchronous
Date: Thu, 04 Feb 2016 13:47:05 +1100	[thread overview]
Message-ID: <87a8nhnqdy.fsf@gnus.org> (raw)
In-Reply-To: <83fux9yend.fsf@gnu.org> (Eli Zaretskii's message of "Wed, 03 Feb 2016 17:52:54 +0200")

Eli Zaretskii <eliz@gnu.org> writes:

>> With async DNS, this will fail, because the process-send-string happens
>> before the connection had completed.  (And this isn't a TLS socket.)  So
>> I think that (like I said on the emacs-devel threads) we may have to
>> change the :nowait stuff to allow a more fine-grained control.
>
> If you make process-send-string wait until DNS completes, the problem
> will disappear.

Yes.  That was basically what the

#ifdef HAVE_GNUTLS
  /* The TLS connection hasn't been set up yet, so we can't write
     anything on the socket. */
  if (!NILP (p->gnutls_boot_parameters))
    return;
#endif

in send_process achieves (in the TLS case).  If we amend that to

  if (!NILP (p->gnutls_boot_parameters) || p->outfd == 0)
    return;

then that will have the same effect on non-TLS sockets.  But as noted in
the previous email, set-process-coding-system would also have to be
changed to remove these outfd guards...

>> make-network-process gives us a process in "open", and then when it
>> changes to "connected" (after connecting the socket) we can't start
>> talking.  We have to wait until the TLS has been negotiated.  So perhaps
>> it should only move to the "connected" state after the negotiation has
>> finished?  Or introduce more states?
>
> Like with process-send-string, we could make gnutls-boot wait until
> DNS resolution completes (and error out if DNS fails).

That's true...  Hm...

> As for making gnutls-boot run in the background, I'm still not
> convinced it buys us enough advantages (or any advantages) to justify
> the changes.  Let's continue discussing that, OK?

I think we've been talking a bit past each other on the TLS issue, so
I'll just write out the scenario as I see it, and why I think it has to
be implemented the way I did it, and you can correct me if you see other
options.

OK: eww has displayed a web page, and now wants to fetch an image over
https.  Our goal is to have Emacs stop as little as possible while this
is happening in the background, so that the user can scroll around or do
whatever the user wants to do while eww is working on getting the image.

So eww issues a url-retrieve command in the background, which ends up
calling make-network-process :nowait t.  This returns immediately, with
no user-noticeable hangs.  getaddrinfo_a has been issued, and after a
while a response is received and is noticed by the idle loop.

Emacs then calls connect_network_process.  This basically is a wrapper
around the connect(2), and it's pretty async on a non-blocking socket,
so this should not be noticeable to the user.

Everything up until now has happened identically for TLS and non-TLS
sockets.

Now, for a TLS socket, we have to do the negotiating.  This is currently
a blocking process, but it doesn't have to be.  The GnuTLS library in
itself is non-blocking, but our interaction with it currently is.

So we call gnutls_boot after the connection has happened.  I originally
did this with a sentinel on a process, but that doesn't really work,
because the callers of make_network_process want their own sentinels on
the process.  So I call gnutls_boot from the C layer instead of from a
sentinel.

No matter how we call gnutls_boot, it will currently hang Emacs while
it's transferring all those certificates back and forth.

After that, the url.el sentinel will fire with a "connect" state, and
it'll say "GET /foo.png" to the server, and the server will output the
image (non-blocking).  And then the image will be parsed and inserted
into the buffer (blocking and noticeable for large images).

*phew*  :-)

> Running gnutls-boot from a separate thread on the C level is also
> possible, but AFAIU that requires a total rewrite of the current C
> implementation, as it does a lot of stuff that cannot be done from a
> non-main thread.

Yup.

> Either way, if we decide that making gnutls-boot run in the background
> is a Good Thing, then I feel that doing so requires code restructuring
> that must involve application-level considerations.

Actually, almost all of the major network usages in Emacs today require
no changes.  The only one I've found is erc.  url.el, Gnus, smtpmail,
imap.el, nntp.el all work without any changes with the current
implementation.

-- 
(domestic pets only, the antidote for overdose, milk.)
   bloggy blog: http://lars.ingebrigtsen.no





  reply	other threads:[~2016-02-04  2:47 UTC|newest]

Thread overview: 30+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2016-01-30  4:00 bug#22493: 25.1.50; open-gnutls-stream doesn't respect :nowait, so the connections are synchronous Lars Ingebrigtsen
2016-01-30  4:45 ` Lars Ingebrigtsen
2016-01-30  9:21   ` Eli Zaretskii
2016-01-30 22:55     ` Lars Ingebrigtsen
2016-01-31  0:40       ` Lars Ingebrigtsen
2016-01-31  1:10         ` Lars Ingebrigtsen
2016-01-31 16:00           ` Eli Zaretskii
2016-01-31 15:59         ` Eli Zaretskii
2016-01-31 23:17           ` Lars Ingebrigtsen
2016-02-01  2:41             ` Lars Ingebrigtsen
2016-02-01  3:41             ` Eli Zaretskii
2016-02-01  4:01               ` Lars Ingebrigtsen
2016-02-01 18:50                 ` Eli Zaretskii
2016-02-02  1:43                   ` Lars Ingebrigtsen
2016-02-02 16:10                     ` Eli Zaretskii
2016-02-03  1:10                       ` Lars Ingebrigtsen
2016-02-03  1:58                         ` Lars Ingebrigtsen
2016-02-03 15:52                           ` Eli Zaretskii
2016-02-04  2:47                             ` Lars Ingebrigtsen [this message]
2016-02-04 16:39                               ` Eli Zaretskii
2016-02-05  2:36                                 ` Lars Ingebrigtsen
2016-02-05  7:24                                   ` Eli Zaretskii
2016-02-05  7:34                                     ` Lars Ingebrigtsen
2016-02-05  9:18                                       ` Eli Zaretskii
2016-02-06  3:03                                         ` Lars Ingebrigtsen
2016-02-06  7:51                                           ` Eli Zaretskii
2016-02-06  7:57                                             ` Lars Ingebrigtsen
2016-02-03 15:51                         ` Eli Zaretskii
2016-02-04  2:59                           ` Lars Ingebrigtsen
2016-01-31 15:57       ` Eli Zaretskii

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

  List information: https://www.gnu.org/software/emacs/

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=87a8nhnqdy.fsf@gnus.org \
    --to=larsi@gnus.org \
    --cc=22493@debbugs.gnu.org \
    --cc=eliz@gnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
Code repositories for project(s) associated with this public inbox

	https://git.savannah.gnu.org/cgit/emacs.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).