mirror of
https://github.com/moparisthebest/curl
synced 2024-12-22 08:08:50 -05:00
- Implemented a protocol independent way to specify blocking direction, used by
transfer.c for blocking. It is currently used only by SCP and SFTP protocols. This enhancement resolves an issue with 100% CPU usage during SFTP upload, reported by Vourhey.
This commit is contained in:
parent
af9ce990f0
commit
66fcebdc9e
6
CHANGES
6
CHANGES
@ -6,6 +6,12 @@
|
|||||||
|
|
||||||
Changelog
|
Changelog
|
||||||
|
|
||||||
|
Kamil Dudka (26 Sep 2009)
|
||||||
|
- Implemented a protocol independent way to specify blocking direction, used by
|
||||||
|
transfer.c for blocking. It is currently used only by SCP and SFTP protocols.
|
||||||
|
This enhancement resolves an issue with 100% CPU usage during SFTP upload,
|
||||||
|
reported by Vourhey.
|
||||||
|
|
||||||
Daniel Stenberg (25 Sep 2009)
|
Daniel Stenberg (25 Sep 2009)
|
||||||
- Chris Mumford filed bug report #2861587
|
- Chris Mumford filed bug report #2861587
|
||||||
(http://curl.haxx.se/bug/view.cgi?id=2861587) identifying that libcurl used
|
(http://curl.haxx.se/bug/view.cgi?id=2861587) identifying that libcurl used
|
||||||
|
30
lib/ssh.c
30
lib/ssh.c
@ -1500,6 +1500,9 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
|
|||||||
result = Curl_setup_transfer(conn, -1, -1, FALSE, NULL,
|
result = Curl_setup_transfer(conn, -1, -1, FALSE, NULL,
|
||||||
FIRSTSOCKET, NULL);
|
FIRSTSOCKET, NULL);
|
||||||
|
|
||||||
|
/* not set by Curl_setup_transfer to preserve keepon bits */
|
||||||
|
conn->sockfd = conn->writesockfd;
|
||||||
|
|
||||||
if(result) {
|
if(result) {
|
||||||
state(conn, SSH_SFTP_CLOSE);
|
state(conn, SSH_SFTP_CLOSE);
|
||||||
sshc->actualcode = result;
|
sshc->actualcode = result;
|
||||||
@ -1911,6 +1914,12 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
|
|||||||
else {
|
else {
|
||||||
result = Curl_setup_transfer(conn, FIRSTSOCKET, data->req.size,
|
result = Curl_setup_transfer(conn, FIRSTSOCKET, data->req.size,
|
||||||
FALSE, NULL, -1, NULL);
|
FALSE, NULL, -1, NULL);
|
||||||
|
|
||||||
|
/* not set by Curl_setup_transfer to preserve keepon bits */
|
||||||
|
conn->writesockfd = conn->sockfd;
|
||||||
|
|
||||||
|
/* FIXME: here should be explained why we need it to start the download */
|
||||||
|
conn->cselect_bits = CURL_CSELECT_IN;
|
||||||
}
|
}
|
||||||
if(result) {
|
if(result) {
|
||||||
state(conn, SSH_SFTP_CLOSE);
|
state(conn, SSH_SFTP_CLOSE);
|
||||||
@ -2031,6 +2040,9 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
|
|||||||
result = Curl_setup_transfer(conn, -1, data->req.size, FALSE, NULL,
|
result = Curl_setup_transfer(conn, -1, data->req.size, FALSE, NULL,
|
||||||
FIRSTSOCKET, NULL);
|
FIRSTSOCKET, NULL);
|
||||||
|
|
||||||
|
/* not set by Curl_setup_transfer to preserve keepon bits */
|
||||||
|
conn->sockfd = conn->writesockfd;
|
||||||
|
|
||||||
if(result) {
|
if(result) {
|
||||||
state(conn, SSH_SCP_CHANNEL_FREE);
|
state(conn, SSH_SCP_CHANNEL_FREE);
|
||||||
sshc->actualcode = result;
|
sshc->actualcode = result;
|
||||||
@ -2080,6 +2092,12 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
|
|||||||
result = Curl_setup_transfer(conn, FIRSTSOCKET,
|
result = Curl_setup_transfer(conn, FIRSTSOCKET,
|
||||||
bytecount, FALSE, NULL, -1, NULL);
|
bytecount, FALSE, NULL, -1, NULL);
|
||||||
|
|
||||||
|
/* not set by Curl_setup_transfer to preserve keepon bits */
|
||||||
|
conn->writesockfd = conn->sockfd;
|
||||||
|
|
||||||
|
/* FIXME: here should be explained why we need it to start the download */
|
||||||
|
conn->cselect_bits = CURL_CSELECT_IN;
|
||||||
|
|
||||||
if(result) {
|
if(result) {
|
||||||
state(conn, SSH_SCP_CHANNEL_FREE);
|
state(conn, SSH_SCP_CHANNEL_FREE);
|
||||||
sshc->actualcode = result;
|
sshc->actualcode = result;
|
||||||
@ -2232,10 +2250,10 @@ static int ssh_perform_getsock(const struct connectdata *conn,
|
|||||||
|
|
||||||
sock[0] = conn->sock[FIRSTSOCKET];
|
sock[0] = conn->sock[FIRSTSOCKET];
|
||||||
|
|
||||||
if(conn->proto.sshc.waitfor & KEEP_RECV)
|
if(conn->waitfor & KEEP_RECV)
|
||||||
bitmap |= GETSOCK_READSOCK(FIRSTSOCKET);
|
bitmap |= GETSOCK_READSOCK(FIRSTSOCKET);
|
||||||
|
|
||||||
if(conn->proto.sshc.waitfor & KEEP_SEND)
|
if(conn->waitfor & KEEP_SEND)
|
||||||
bitmap |= GETSOCK_WRITESOCK(FIRSTSOCKET);
|
bitmap |= GETSOCK_WRITESOCK(FIRSTSOCKET);
|
||||||
|
|
||||||
return bitmap;
|
return bitmap;
|
||||||
@ -2279,15 +2297,17 @@ static void ssh_block2waitfor(struct connectdata *conn, bool block)
|
|||||||
{
|
{
|
||||||
struct ssh_conn *sshc = &conn->proto.sshc;
|
struct ssh_conn *sshc = &conn->proto.sshc;
|
||||||
int dir;
|
int dir;
|
||||||
if(block && (dir = libssh2_session_block_directions(sshc->ssh_session))) {
|
if(!block)
|
||||||
|
conn->waitfor = 0;
|
||||||
|
else if((dir = libssh2_session_block_directions(sshc->ssh_session))) {
|
||||||
/* translate the libssh2 define bits into our own bit defines */
|
/* translate the libssh2 define bits into our own bit defines */
|
||||||
sshc->waitfor = ((dir&LIBSSH2_SESSION_BLOCK_INBOUND)?KEEP_RECV:0) |
|
conn->waitfor = ((dir&LIBSSH2_SESSION_BLOCK_INBOUND)?KEEP_RECV:0) |
|
||||||
((dir&LIBSSH2_SESSION_BLOCK_OUTBOUND)?KEEP_SEND:0);
|
((dir&LIBSSH2_SESSION_BLOCK_OUTBOUND)?KEEP_SEND:0);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
/* It didn't block or libssh2 didn't reveal in which direction, put back
|
/* It didn't block or libssh2 didn't reveal in which direction, put back
|
||||||
the original set */
|
the original set */
|
||||||
sshc->waitfor = sshc->orig_waitfor;
|
conn->waitfor = sshc->orig_waitfor;
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
/* no libssh2 directional support so we simply don't know */
|
/* no libssh2 directional support so we simply don't know */
|
||||||
|
@ -1652,10 +1652,6 @@ CURLcode Curl_readwrite(struct connectdata *conn,
|
|||||||
|
|
||||||
if((k->keepon & KEEP_RECVBITS) == KEEP_RECV) {
|
if((k->keepon & KEEP_RECVBITS) == KEEP_RECV) {
|
||||||
fd_read = conn->sockfd;
|
fd_read = conn->sockfd;
|
||||||
#if defined(USE_LIBSSH2)
|
|
||||||
if(conn->protocol & (PROT_SCP|PROT_SFTP))
|
|
||||||
select_res |= CURL_CSELECT_IN;
|
|
||||||
#endif /* USE_LIBSSH2 */
|
|
||||||
} else
|
} else
|
||||||
fd_read = CURL_SOCKET_BAD;
|
fd_read = CURL_SOCKET_BAD;
|
||||||
|
|
||||||
@ -1884,33 +1880,39 @@ Transfer(struct connectdata *conn)
|
|||||||
return CURLE_OK;
|
return CURLE_OK;
|
||||||
|
|
||||||
while(!done) {
|
while(!done) {
|
||||||
curl_socket_t fd_read;
|
curl_socket_t fd_read = conn->sockfd;
|
||||||
curl_socket_t fd_write;
|
curl_socket_t fd_write = conn->writesockfd;
|
||||||
|
int keepon = k->keepon;
|
||||||
|
|
||||||
|
if(conn->waitfor) {
|
||||||
|
/* if waitfor is set, get the RECV and SEND bits from that but keep the
|
||||||
|
other bits */
|
||||||
|
keepon &= ~ (KEEP_RECV|KEEP_SEND);
|
||||||
|
keepon |= conn->waitfor & (KEEP_RECV|KEEP_SEND);
|
||||||
|
}
|
||||||
|
|
||||||
/* limit-rate logic: if speed exceeds threshold, then do not include fd in
|
/* limit-rate logic: if speed exceeds threshold, then do not include fd in
|
||||||
select set. The current speed is recalculated in each Curl_readwrite()
|
select set. The current speed is recalculated in each Curl_readwrite()
|
||||||
call */
|
call */
|
||||||
if((k->keepon & KEEP_SEND) &&
|
if((keepon & KEEP_SEND) &&
|
||||||
(!data->set.max_send_speed ||
|
(!data->set.max_send_speed ||
|
||||||
(data->progress.ulspeed < data->set.max_send_speed) )) {
|
(data->progress.ulspeed < data->set.max_send_speed) )) {
|
||||||
fd_write = conn->writesockfd;
|
|
||||||
k->keepon &= ~KEEP_SEND_HOLD;
|
k->keepon &= ~KEEP_SEND_HOLD;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
fd_write = CURL_SOCKET_BAD;
|
fd_write = CURL_SOCKET_BAD;
|
||||||
if(k->keepon & KEEP_SEND)
|
if(keepon & KEEP_SEND)
|
||||||
k->keepon |= KEEP_SEND_HOLD; /* hold it */
|
k->keepon |= KEEP_SEND_HOLD; /* hold it */
|
||||||
}
|
}
|
||||||
|
|
||||||
if((k->keepon & KEEP_RECV) &&
|
if((keepon & KEEP_RECV) &&
|
||||||
(!data->set.max_recv_speed ||
|
(!data->set.max_recv_speed ||
|
||||||
(data->progress.dlspeed < data->set.max_recv_speed)) ) {
|
(data->progress.dlspeed < data->set.max_recv_speed)) ) {
|
||||||
fd_read = conn->sockfd;
|
|
||||||
k->keepon &= ~KEEP_RECV_HOLD;
|
k->keepon &= ~KEEP_RECV_HOLD;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
fd_read = CURL_SOCKET_BAD;
|
fd_read = CURL_SOCKET_BAD;
|
||||||
if(k->keepon & KEEP_RECV)
|
if(keepon & KEEP_RECV)
|
||||||
k->keepon |= KEEP_RECV_HOLD; /* hold it */
|
k->keepon |= KEEP_RECV_HOLD; /* hold it */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -568,7 +568,6 @@ struct ssh_conn {
|
|||||||
LIBSSH2_CHANNEL *ssh_channel; /* Secure Shell channel handle */
|
LIBSSH2_CHANNEL *ssh_channel; /* Secure Shell channel handle */
|
||||||
LIBSSH2_SFTP *sftp_session; /* SFTP handle */
|
LIBSSH2_SFTP *sftp_session; /* SFTP handle */
|
||||||
LIBSSH2_SFTP_HANDLE *sftp_handle;
|
LIBSSH2_SFTP_HANDLE *sftp_handle;
|
||||||
int waitfor; /* current READ/WRITE bits to wait for */
|
|
||||||
int orig_waitfor; /* default READ/WRITE bits wait for */
|
int orig_waitfor; /* default READ/WRITE bits wait for */
|
||||||
|
|
||||||
/* note that HAVE_LIBSSH2_KNOWNHOST_API is a define set in the libssh2.h
|
/* note that HAVE_LIBSSH2_KNOWNHOST_API is a define set in the libssh2.h
|
||||||
@ -1075,6 +1074,8 @@ struct connectdata {
|
|||||||
} proto;
|
} proto;
|
||||||
|
|
||||||
int cselect_bits; /* bitmask of socket events */
|
int cselect_bits; /* bitmask of socket events */
|
||||||
|
int waitfor; /* current READ/WRITE bits to wait for */
|
||||||
|
|
||||||
#if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI)
|
#if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI)
|
||||||
int socks5_gssapi_enctype;
|
int socks5_gssapi_enctype;
|
||||||
#endif
|
#endif
|
||||||
|
Loading…
Reference in New Issue
Block a user