GNOME Bugzilla – Bug 621791
Connection terminated unexpectedly, during login. Connection should have been restarted instead
Last modified: 2010-11-09 17:37:20 UTC
When using libsoup on windows to login from a client to a server, I get: Status code 7, Connection terminated unexpectedly. (The client is using asyncronous I/O) On Linux and Mac OS. Looking at the exact same scenario using libsoup on Linux or Mac OS, I can see from the log, that libsoup on both those platforms first tries to send the message containing the login info. Immediately hereafter, it sends the message again and the log tells that the connection is restarted. The server responds with a status code 302, Found and is redirected to the new location. I'll try to explain the scenario in more detail. 1) From client to server: GET https://host/path1?query1 2) From server to client: HTTP/1.1 200 OK Body contains request for userid and password 3) User types password (this will normally take a few seconds) 4) From client to server: POST https://host/path2 Content-Type: application/x-www-form-urlencoded Body containing userid and password 5a) On Windows I experience: Status code 7, Connection terminated unexpectedly. 5b) On Linux and MacOS I experience: SoupSessionAsync, restarted From client to server: Message from 4) is now sent to the server. 6) From server to client: HTTP/1.1 302 Found Location: /path3 7) From client to server: GET https://host/path3 8) From server to client: HTTP/1.1 200 OK etc. It seems that libsoup on both Linus and Mac OS restart the connection in step 5, where as it is not restarted when using libsoup on Windows. If I programmatically inserts the userid and password, so that there are nearly no delay between step 2 and 4, the request in step 4 is succesfull on Windows too. It seems that the server closes the connection after a very short time-out and this is causing problems on Windows, where libsoup apparently do not restart the connection like it does on Linux and Mac OS.
Yeah, a year ago it would have failed on Linux and Mac too, but I put in a hack that fixes it for "unix" but not Windows (http://git.gnome.org/browse/libsoup/commit/?id=ef7fc0585990b9c2e056596d1850bdb3f6f6dae9) This will hopefully be fixed in 2.32/3.0. If you need a fix now, try this: add a method soup_socket_get_iochannel() to return the socket's iochannel, and in soup_connection_get_state(), on windows create the GPollFD using g_io_channel_win32_make_pollfd() on the iochannel. (And then pass it into g_poll just like in the unix case.) If that works then I can add something like that to the 2.30 branch.
I've tried to add the proposed fix. Unfortunately it seems to crash the application the second time g_io_channel_win32_make_pollfd() is called.
hm... can you attach your patch?
Here it comes In soup-socket.h: GIOChannel * soup_socket_get_iochannel (SoupSocket *sock); In soup-socket.c: GIOChannel * soup_socket_get_iochannel (SoupSocket *sock) { GIOChannel * iochannel = NULL; g_return_val_if_fail (SOUP_IS_SOCKET (sock), NULL); if(SOUP_SOCKET_GET_PRIVATE (sock)->sockfd != -1) { iochannel = SOUP_SOCKET_GET_PRIVATE (sock)->iochannel; } return iochannel; } In soup-connection.c: In function soup_connection_gt_state(), just after the G_OS_UNIX stuff #ifdef G_OS_WIN32 if (priv->state == SOUP_CONNECTION_IDLE) { GIOChannel * iochannel; GPollFD pfd; iochannel = soup_socket_get_iochannel (priv->socket); if(iochannel != NULL) { g_io_channel_win32_make_pollfd(iochannel, G_IO_IN, &pfd); if (g_poll (&pfd, 1, 0) == 1) soup_connection_set_state (conn, SOUP_CONNECTION_REMOTE_DISCONNECTED); } } #endif
hm... g_io_channel_win32_make_pollfd is kinda weird. it's possible you can only call it once per iochannel. So I guess instead of soup_socket_get_iochannel(), you'd want soup_socket_get_pollfd(), where the first time you call it it would call g_io_channel_win32_make_pollfd() on its iochannel, and it would store that result in socket->priv, and return the same pollfd later when it was called again... (this is all part of why I didn't bother trying to fix it on windows before :)
I have now tried this too. Unfortunately with same bad result the second time g_io_channel_win32_make_pollfd() is called. Looking into g_io_channel_win32_make_pollfd() shows that WSACreateEvent() is called. WSACreateEvent() do not take any parameters. So it doesn't seems to have any clue about iochannel. From the WSACreateEvent() description on MSDN, I don't really get any clue about how it is supposed to be used and why it crashes. Added in soup-socket.c: (Both priv->iochannel and priv->pfd are initialized to NULL in soup_socket_init() ) GPollFD * soup_socket_get_pollfd (SoupSocket *sock) { SoupSocketPrivate *priv; g_return_val_if_fail (SOUP_IS_SOCKET (sock), NULL); priv = SOUP_SOCKET_GET_PRIVATE (sock); g_return_val_if_fail (priv->sockfd != -1, NULL); g_return_val_if_fail (priv->iochannel != NULL, NULL); if(priv->pfd == NULL) { priv->pfd = g_new0 (GPollFD, 1); g_io_channel_win32_make_pollfd(priv->iochannel, G_IO_IN, priv->pfd); } return priv->pfd; }
this will be fixed by the port to using GSocketConnection. I'm marking this as a dup of the "use gio tls" bug, since that's the thing that's blocking the move to GSocketConnection *** This bug has been marked as a duplicate of bug 634425 ***