Commit 66fcebdc authored by Kamil Dudka's avatar Kamil Dudka
Browse files

- 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.
parent af9ce990
Loading
Loading
Loading
Loading
+6 −0
Original line number Diff line number Diff line
@@ -6,6 +6,12 @@

                                  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)
- Chris Mumford filed bug report #2861587
  (http://curl.haxx.se/bug/view.cgi?id=2861587) identifying that libcurl used
+25 −5
Original line number Diff line number Diff line
@@ -1500,6 +1500,9 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
    result = Curl_setup_transfer(conn, -1, -1, FALSE, NULL,
                                 FIRSTSOCKET, NULL);

    /* not set by Curl_setup_transfer to preserve keepon bits */
    conn->sockfd = conn->writesockfd;

    if(result) {
      state(conn, SSH_SFTP_CLOSE);
      sshc->actualcode = result;
@@ -1911,6 +1914,12 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
  else {
    result = Curl_setup_transfer(conn, FIRSTSOCKET, data->req.size,
                                 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) {
    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,
                                 FIRSTSOCKET, NULL);

    /* not set by Curl_setup_transfer to preserve keepon bits */
    conn->sockfd = conn->writesockfd;

    if(result) {
      state(conn, SSH_SCP_CHANNEL_FREE);
      sshc->actualcode = result;
@@ -2080,6 +2092,12 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
    result = Curl_setup_transfer(conn, FIRSTSOCKET,
                                 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) {
      state(conn, SSH_SCP_CHANNEL_FREE);
      sshc->actualcode = result;
@@ -2232,10 +2250,10 @@ static int ssh_perform_getsock(const struct connectdata *conn,

  sock[0] = conn->sock[FIRSTSOCKET];

  if(conn->proto.sshc.waitfor & KEEP_RECV)
  if(conn->waitfor & KEEP_RECV)
    bitmap |= GETSOCK_READSOCK(FIRSTSOCKET);

  if(conn->proto.sshc.waitfor & KEEP_SEND)
  if(conn->waitfor & KEEP_SEND)
    bitmap |= GETSOCK_WRITESOCK(FIRSTSOCKET);

  return bitmap;
@@ -2279,15 +2297,17 @@ static void ssh_block2waitfor(struct connectdata *conn, bool block)
{
  struct ssh_conn *sshc = &conn->proto.sshc;
  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 */
    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);
  }
  else
    /* It didn't block or libssh2 didn't reveal in which direction, put back
       the original set */
    sshc->waitfor = sshc->orig_waitfor;
    conn->waitfor = sshc->orig_waitfor;
}
#else
  /* no libssh2 directional support so we simply don't know */
+14 −12
Original line number Diff line number Diff line
@@ -1652,10 +1652,6 @@ CURLcode Curl_readwrite(struct connectdata *conn,

  if((k->keepon & KEEP_RECVBITS) == KEEP_RECV) {
    fd_read = conn->sockfd;
#if defined(USE_LIBSSH2)
    if(conn->protocol & (PROT_SCP|PROT_SFTP))
      select_res |= CURL_CSELECT_IN;
#endif /* USE_LIBSSH2 */
  } else
    fd_read = CURL_SOCKET_BAD;

@@ -1884,33 +1880,39 @@ Transfer(struct connectdata *conn)
    return CURLE_OK;

  while(!done) {
    curl_socket_t fd_read;
    curl_socket_t fd_write;
    curl_socket_t fd_read = conn->sockfd;
    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
       select set. The current speed is recalculated in each Curl_readwrite()
       call */
    if((k->keepon & KEEP_SEND) &&
    if((keepon & KEEP_SEND) &&
        (!data->set.max_send_speed ||
         (data->progress.ulspeed < data->set.max_send_speed) )) {
      fd_write = conn->writesockfd;
      k->keepon &= ~KEEP_SEND_HOLD;
    }
    else {
      fd_write = CURL_SOCKET_BAD;
      if(k->keepon & KEEP_SEND)
      if(keepon & KEEP_SEND)
        k->keepon |= KEEP_SEND_HOLD; /* hold it */
    }

    if((k->keepon & KEEP_RECV) &&
    if((keepon & KEEP_RECV) &&
        (!data->set.max_recv_speed ||
         (data->progress.dlspeed < data->set.max_recv_speed)) ) {
      fd_read = conn->sockfd;
      k->keepon &= ~KEEP_RECV_HOLD;
    }
    else {
      fd_read = CURL_SOCKET_BAD;
      if(k->keepon & KEEP_RECV)
      if(keepon & KEEP_RECV)
        k->keepon |= KEEP_RECV_HOLD; /* hold it */
    }

+2 −1
Original line number Diff line number Diff line
@@ -568,7 +568,6 @@ struct ssh_conn {
  LIBSSH2_CHANNEL *ssh_channel; /* Secure Shell channel handle */
  LIBSSH2_SFTP *sftp_session;   /* 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 */

  /* note that HAVE_LIBSSH2_KNOWNHOST_API is a define set in the libssh2.h
@@ -1075,6 +1074,8 @@ struct connectdata {
  } proto;

  int cselect_bits; /* bitmask of socket events */
  int waitfor;      /* current READ/WRITE bits to wait for */

#if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI)
  int socks5_gssapi_enctype;
#endif