1
0
mirror of https://github.com/moparisthebest/curl synced 2024-12-22 08:08:50 -05:00

- Jeff Weber reported memory leaks with aborted SCP and SFTP transfers and

provided excellent repeat recipes. I fixed the cases I managed to reproduce
  but Jeff still got some (SCP) problems even after these fixes:
  http://curl.haxx.se/mail/lib-2008-05/0342.html
This commit is contained in:
Daniel Stenberg 2008-05-28 20:31:28 +00:00
parent c62d55342d
commit b49dcfb52b
3 changed files with 64 additions and 32 deletions

View File

@ -7,6 +7,12 @@
Changelog Changelog
Daniel Stenberg (28 May 2008)
- Jeff Weber reported memory leaks with aborted SCP and SFTP transfers and
provided excellent repeat recipes. I fixed the cases I managed to reproduce
but Jeff still got some (SCP) problems even after these fixes:
http://curl.haxx.se/mail/lib-2008-05/0342.html
Daniel Stenberg (26 May 2008) Daniel Stenberg (26 May 2008)
- Bug report #1973352 (http://curl.haxx.se/bug/view.cgi?id=1973352) identified - Bug report #1973352 (http://curl.haxx.se/bug/view.cgi?id=1973352) identified
how the HTTP redirect following code didn't properly follow to a new URL if how the HTTP redirect following code didn't properly follow to a new URL if

View File

@ -38,6 +38,7 @@ This release includes the following bugfixes:
o several curl_multi_socket() fixes o several curl_multi_socket() fixes
o builds fine for Haiku OS o builds fine for Haiku OS
o follow redirect with only a new query string o follow redirect with only a new query string
o SCP and SFTP memory leaks on aborted transfers
This release includes the following known bugs: This release includes the following known bugs:
@ -60,6 +61,6 @@ advice from friends like these:
Rafa Muyo, Andre Guibert de Bruet, Brock Noland, Sandor Feldi, Stefan Krause, Rafa Muyo, Andre Guibert de Bruet, Brock Noland, Sandor Feldi, Stefan Krause,
David Shaw, Norbert Frese, Bart Whiteley, Jean-Francois Bertrand, Ben Van Hof, David Shaw, Norbert Frese, Bart Whiteley, Jean-Francois Bertrand, Ben Van Hof,
Yuriy Sosov, Christopher Palow, Yang Tse, Liam Healy, Nikolai Kondrashov, Yuriy Sosov, Christopher Palow, Yang Tse, Liam Healy, Nikolai Kondrashov,
David Rosenstrauch, Andreas Faerber, Scott McCreary David Rosenstrauch, Andreas Faerber, Scott McCreary, Jeff Weber
Thanks! (and sorry if I forgot to mention someone) Thanks! (and sorry if I forgot to mention someone)

View File

@ -1698,6 +1698,20 @@ static CURLcode ssh_statemach_act(struct connectdata *conn)
break; break;
case SSH_SFTP_SHUTDOWN: case SSH_SFTP_SHUTDOWN:
/* during times we get here due to a broken transfer and then the
sftp_handle might not have been taken down so make sure that is done
before we proceed */
if(sshc->sftp_handle) {
rc = libssh2_sftp_close(sshc->sftp_handle);
if(rc == LIBSSH2_ERROR_EAGAIN) {
break;
}
else if(rc < 0) {
infof(data, "Failed to close libssh2 file\n");
}
sshc->sftp_handle = NULL;
}
if(sshc->sftp_session) { if(sshc->sftp_session) {
rc = libssh2_sftp_shutdown(sshc->sftp_session); rc = libssh2_sftp_shutdown(sshc->sftp_session);
if(rc == LIBSSH2_ERROR_EAGAIN) { if(rc == LIBSSH2_ERROR_EAGAIN) {
@ -1893,6 +1907,20 @@ static CURLcode ssh_statemach_act(struct connectdata *conn)
break; break;
case SSH_SESSION_DISCONNECT: case SSH_SESSION_DISCONNECT:
/* during weird times when we've been prematurely aborted, the channel
is still alive when we reach this state and we MUST kill the channel
properly first */
if(sshc->ssh_channel) {
rc = libssh2_channel_free(sshc->ssh_channel);
if(rc == LIBSSH2_ERROR_EAGAIN) {
break;
}
else if(rc < 0) {
infof(data, "Failed to free libssh2 scp subsystem\n");
}
sshc->ssh_channel = NULL;
}
if(sshc->ssh_session) { if(sshc->ssh_session) {
rc = libssh2_session_disconnect(sshc->ssh_session, "Shutdown"); rc = libssh2_session_disconnect(sshc->ssh_session, "Shutdown");
if(rc == LIBSSH2_ERROR_EAGAIN) { if(rc == LIBSSH2_ERROR_EAGAIN) {
@ -2152,23 +2180,25 @@ static CURLcode scp_disconnect(struct connectdata *conn)
Curl_safefree(conn->data->state.proto.ssh); Curl_safefree(conn->data->state.proto.ssh);
conn->data->state.proto.ssh = NULL; conn->data->state.proto.ssh = NULL;
if(conn->proto.sshc.ssh_session) {
/* only if there's a session still around to use! */
state(conn, SSH_SESSION_DISCONNECT); state(conn, SSH_SESSION_DISCONNECT);
result = ssh_easy_statemach(conn); result = ssh_easy_statemach(conn);
}
return result; return result;
} }
static CURLcode scp_done(struct connectdata *conn, CURLcode status, /* generic done function for both SCP and SFTP called from their specific
bool premature) done functions */
static CURLcode ssh_done(struct connectdata *conn, CURLcode status)
{ {
CURLcode result = CURLE_OK; CURLcode result = CURLE_OK;
bool done = FALSE; bool done = FALSE;
(void)premature; /* not used */
(void)status; /* unused */
if(status == CURLE_OK) { if(status == CURLE_OK) {
state(conn, SSH_SCP_DONE);
/* run the state-machine */ /* run the state-machine */
if(conn->data->state.used_interface == Curl_if_multi) { if(conn->data->state.used_interface == Curl_if_multi) {
result = ssh_multi_statemach(conn, &done); result = ssh_multi_statemach(conn, &done);
@ -2185,12 +2215,25 @@ static CURLcode scp_done(struct connectdata *conn, CURLcode status,
if(done) { if(done) {
struct SSHPROTO *sftp_scp = conn->data->state.proto.ssh; struct SSHPROTO *sftp_scp = conn->data->state.proto.ssh;
Curl_safefree(sftp_scp->path); Curl_safefree(sftp_scp->path);
sftp_scp->path = NULL; sftp_scp->path = NULL;
Curl_pgrsDone(conn); Curl_pgrsDone(conn);
} }
return result; return result;
}
static CURLcode scp_done(struct connectdata *conn, CURLcode status,
bool premature)
{
(void)premature; /* not used */
if(status == CURLE_OK)
state(conn, SSH_SCP_DONE);
return ssh_done(conn, status);
} }
@ -2295,8 +2338,11 @@ static CURLcode sftp_disconnect(struct connectdata *conn)
Curl_safefree(conn->data->state.proto.ssh); Curl_safefree(conn->data->state.proto.ssh);
conn->data->state.proto.ssh = NULL; conn->data->state.proto.ssh = NULL;
if(conn->proto.sshc.ssh_session) {
/* only if there's a session still around to use! */
state(conn, SSH_SFTP_SHUTDOWN); state(conn, SSH_SFTP_SHUTDOWN);
result = ssh_easy_statemach(conn); result = ssh_easy_statemach(conn);
}
DEBUGF(infof(conn->data, "SSH DISCONNECT is done\n")); DEBUGF(infof(conn->data, "SSH DISCONNECT is done\n"));
@ -2307,12 +2353,8 @@ static CURLcode sftp_disconnect(struct connectdata *conn)
static CURLcode sftp_done(struct connectdata *conn, CURLcode status, static CURLcode sftp_done(struct connectdata *conn, CURLcode status,
bool premature) bool premature)
{ {
CURLcode result = CURLE_OK;
bool done = FALSE;
struct ssh_conn *sshc = &conn->proto.sshc; struct ssh_conn *sshc = &conn->proto.sshc;
(void)status; /* unused */
if(status == CURLE_OK) { if(status == CURLE_OK) {
/* Before we shut down, see if there are any post-quote commands to send: */ /* Before we shut down, see if there are any post-quote commands to send: */
if(!status && !premature && conn->data->set.postquote) { if(!status && !premature && conn->data->set.postquote) {
@ -2321,25 +2363,8 @@ static CURLcode sftp_done(struct connectdata *conn, CURLcode status,
} }
else else
state(conn, SSH_SFTP_CLOSE); state(conn, SSH_SFTP_CLOSE);
/* run the state-machine */
if(conn->data->state.used_interface == Curl_if_multi)
result = ssh_multi_statemach(conn, &done);
else {
result = ssh_easy_statemach(conn);
done = TRUE;
} }
} return ssh_done(conn, status);
else {
result = status;
done = TRUE;
}
if(done) {
Curl_pgrsDone(conn);
}
return result;
} }
/* return number of sent bytes */ /* return number of sent bytes */