G_SOCKET_CLIENT_RESOLVING improperly emitted on final iteration of GSocketAddressEnumerator
Spotted thanks to some debug posted by @lovetox in another issue. In gsocketclient.c, enumerator_next_async(), we call g_socket_client_emit_event() with G_SOCKET_CLIENT_RESOLVING before calling g_socket_address_enumerator_next_async(). Ditto for the sync g_socket_client_connect(). But this isn't right for the final iteration of the GSocketAddressEnumerator, because on the final iteration it's just going to return NULL without attempting to resolve any address. That's how we wind up with traces like this:
<Gio.SocketClient object at 0x7fa37362cbe0 (GSocketClient at 0x2405b40)> <enum G_SOCKET_CLIENT_RESOLVING of type Gio.SocketClientEvent> <Gio.InetSocketAddress object at 0x7fa3736282d0 (GInetSocketAddress at 0x24d3120)> None
<Gio.SocketClient object at 0x7fa37362cbe0 (GSocketClient at 0x2405b40)> <enum G_SOCKET_CLIENT_RESOLVED of type Gio.SocketClientEvent> <Gio.InetSocketAddress object at 0x7fa3736333c0 (GInetSocketAddress at 0x24d3120)> None
<Gio.SocketClient object at 0x7fa37362cbe0 (GSocketClient at 0x2405b40)> <enum G_SOCKET_CLIENT_CONNECTING of type Gio.SocketClientEvent> <Gio.InetSocketAddress object at 0x7fa3736333c0 (GInetSocketAddress at 0x24d3120)> <Gio.TcpConnection object at 0x7fa373633d20 (GTcpConnection at 0x252d0f0)>
<Gio.SocketClient object at 0x7fa37362cbe0 (GSocketClient at 0x2405b40)> <enum G_SOCKET_CLIENT_CONNECTED of type Gio.SocketClientEvent> <Gio.InetSocketAddress object at 0x7fa3736333c0 (GInetSocketAddress at 0x24d3120)> <Gio.TcpConnection object at 0x7fa373633d20 (GTcpConnection at 0x252d0f0)>
<Gio.SocketClient object at 0x7fa37362cbe0 (GSocketClient at 0x2405b40)> <enum G_SOCKET_CLIENT_PROXY_NEGOTIATING of type Gio.SocketClientEvent> <Gio.InetSocketAddress object at 0x7fa3736333c0 (GInetSocketAddress at 0x24d3120)> <Gio.TcpConnection object at 0x7fa373633d20 (GTcpConnection at 0x252d0f0)>
<Gio.SocketClient object at 0x7fa37362cbe0 (GSocketClient at 0x2405b40)> <enum G_SOCKET_CLIENT_RESOLVING of type Gio.SocketClientEvent> <Gio.InetSocketAddress object at 0x7fa3736333c0 (GInetSocketAddress at 0x24d3120)> None
<Gio.SocketClient object at 0x7fa37362cbe0 (GSocketClient at 0x2405b40)> <enum G_SOCKET_CLIENT_COMPLETE of type Gio.SocketClientEvent> <Gio.InetSocketAddress object at 0x7fa3736333c0 (GInetSocketAddress at 0x24d3120)> None
where G_SOCKET_CLIENT_RESOLVING is emitted right before G_SOCKET_CLIENT_COMPLETE. This should be easy to test for (I'd say a basic requirement to introduce code that emits events would be a test that checks whether they're emitted in the expected order), but the only tests we have for GSocketClient are the happy eyeballs tests, and they don't check the order events are emitted in.
It's going to be tricky to solve because it requires new API in GSocketAddressEnumerator to peek at whether the next iteration will perform a resolution or finish the enumeration. And I don't think it can be private API, because the GSocketClient's GSocketConnectable could return a GSocketEnumerator that's not implemented by GLib.
Note that this bug is not always going to occur, because GSocketClient will not fully iterate the GSocketAddressEnumerator unless it has to.
Also note: although I do think it's a bug, it's relatively minor, and since the changes required to solve it would be intrusive, I wouldn't recommend prioritizing this over more serious issues.