Commit c2459c43 authored by Daniel Stenberg's avatar Daniel Stenberg
Browse files

multi: conn goes bad when data change

Within multi_socket when conn is used as a shorthand, data could be
changed and multi_runsingle could modify the connectdata struct to deal
with. This bug has not been included in a public release.

Using 'conn' like that turned out to be ugly. This change is a partial
revert of commit f1c6cd42.

Reported by: Miroslav Spousta
Bug: http://curl.haxx.se/bug/view.cgi?id=3265485
parent c37ad9e9
Loading
Loading
Loading
Loading
+11 −15
Original line number Diff line number Diff line
@@ -2105,41 +2105,37 @@ static CURLMcode multi_socket(struct Curl_multi *multi,
         and just move on. */
      ;
    else {
      struct connectdata *conn;
      data = entry->easy;

      if(data->magic != CURLEASY_MAGIC_NUMBER)
        /* bad bad bad bad bad bad bad */
        return CURLM_INTERNAL_ERROR;

      /* note that this can possibly be NULL at this point */
      conn = data->set.one_easy->easy_conn;

      /* If the pipeline is enabled, take the handle which is in the head of
         the pipeline. If we should write into the socket, take the send_pipe
         head.  If we should read from the socket, take the recv_pipe head. */
      if(conn) {
      if(data->set.one_easy->easy_conn) {
        if ((ev_bitmask & CURL_POLL_OUT) &&
            conn->send_pipe &&
            conn->send_pipe->head)
          data = conn->send_pipe->head->ptr;
            data->set.one_easy->easy_conn->send_pipe &&
            data->set.one_easy->easy_conn->send_pipe->head)
          data = data->set.one_easy->easy_conn->send_pipe->head->ptr;
        else if ((ev_bitmask & CURL_POLL_IN) &&
                 conn->recv_pipe &&
                 conn->recv_pipe->head)
          data = conn->recv_pipe->head->ptr;
                 data->set.one_easy->easy_conn->recv_pipe &&
                 data->set.one_easy->easy_conn->recv_pipe->head)
          data = data->set.one_easy->easy_conn->recv_pipe->head->ptr;
      }

      if(conn && !(conn->handler->flags & PROTOPT_DIRLOCK))
      if(data->set.one_easy->easy_conn && !(data->set.one_easy->easy_conn->handler->flags & PROTOPT_DIRLOCK))
        /* set socket event bitmask if they're not locked */
        conn->cselect_bits = ev_bitmask;
        data->set.one_easy->easy_conn->cselect_bits = ev_bitmask;

      do
        result = multi_runsingle(multi, now, data->set.one_easy);
      while (CURLM_CALL_MULTI_PERFORM == result);

      if(conn && !(conn->handler->flags & PROTOPT_DIRLOCK))
      if(data->set.one_easy->easy_conn && !(data->set.one_easy->easy_conn->handler->flags & PROTOPT_DIRLOCK))
        /* clear the bitmask only if not locked */
        conn->cselect_bits = 0;
        data->set.one_easy->easy_conn->cselect_bits = 0;

      if(CURLM_OK >= result)
        /* get the socket(s) and check if the state has been changed since