Subject: Re: bug#22493: 25.1.50; open-gnutls-stream doesn't respect :nowait, so the connections are synchronous

From: Eli Zaretskii <[email-masked]>
Date: Wed, 03 Feb 2016 17:52:54 +0200

> From: Lars Ingebrigtsen <[email-masked]>
> Cc: [email-masked]
> Date: Wed, 03 Feb 2016 12:58:30 +1100
> 
> I think you're right again.  I thought I had tested this, but I hadn't:
> 
> (progn
>   (setq proc (make-network-process :name "foo"
>                                    :buffer (get-buffer-create "*foo*")
>                                    :host "gmane.org"
>                                    :service "http"
>                                    :nowait t))
>   (process-send-string proc "GET / HTTP/1.0\n\n"))
> 
> 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.  Then, if code such as above wants better async
behavior, its maintainer will have to restructure the code, for
example like this:

> So the rule would be if you want a fully async connection, you have to
> say ":nowait 'dns" or something, and then put a sentinel on the process
> to not do anything until it changes status to "connected".  (This is
> what url.el does already, which is why I didn't see this before...)

But if the code is not changed, it should still "just work", albeit
not as fast as it could.

> With a TLS socket:
> 
> 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).

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?

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.

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.  So these changes
probably shouldn't be done on the level of open-gnutls-stream.
Instead, we should provide the building blocks for applications that
want this, and let them restructure their code as they see fit.
Trying to do that transparently controlled by a single argument is not
going to work well, I think.