Hello community, here is the log from the commit of package curl for openSUSE:Factory checked in at 2012-11-10 16:55:38 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/curl (Old) and /work/SRC/openSUSE:Factory/.curl.new (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Package is "curl", Maintainer is "VCizek@suse.com" Changes: -------- --- /work/SRC/openSUSE:Factory/curl/curl.changes 2012-07-30 20:15:23.000000000 +0200 +++ /work/SRC/openSUSE:Factory/.curl.new/curl.changes 2012-11-10 16:55:42.000000000 +0100 @@ -1,0 +2,7 @@ +Sun Nov 4 19:57:33 UTC 2012 - gber@opensuse.org + +- added curl-ftp-prevent-the-multi-interface-from-blocking.patch in + order to prevent the multi interface from blocking when using ftp + and the remote end responds very slowly (sf#3579064) + +------------------------------------------------------------------- New: ---- curl-ftp-prevent-the-multi-interface-from-blocking.patch ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ curl.spec ++++++ --- /var/tmp/diff_new_pack.hbbjQm/_old 2012-11-10 16:55:43.000000000 +0100 +++ /var/tmp/diff_new_pack.hbbjQm/_new 2012-11-10 16:55:43.000000000 +0100 @@ -24,7 +24,7 @@ Version: 7.27.0 Release: 0 Summary: A Tool for Transferring Data from URLs -License: BSD-3-Clause ; MIT +License: BSD-3-Clause and MIT Group: Productivity/Networking/Web/Utilities Url: http://curl.haxx.se/ Source: http://curl.haxx.se/download/%{name}-%{version}.tar.lzma @@ -32,6 +32,8 @@ Source3: baselibs.conf Patch: libcurl-ocloexec.patch Patch1: dont-mess-with-rpmoptflags.diff +# PATCH-FIX-UPSTREAM curl-ftp-prevent-the-multi-interface-from-blocking.patch sf#3579064 gber@opensuse.org -- Prevent the multi interface from blocking when using ftp and the remote end responds very slowly (backported from upstream git) +Patch2: curl-ftp-prevent-the-multi-interface-from-blocking.patch BuildRequires: libidn-devel BuildRequires: libtool BuildRequires: lzma @@ -91,6 +93,7 @@ %setup -q %patch %patch1 +%patch2 -p1 %build autoreconf -fi ++++++ curl-ftp-prevent-the-multi-interface-from-blocking.patch ++++++
From b2954e66e87be7414a4508f8167ca531e653bea8 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg <daniel@haxx.se> Date: Sun, 4 Nov 2012 18:22:48 +0100 Subject: [PATCH] FTP: prevent the multi interface from blocking
As pointed out in Bug report #3579064, curl_multi_perform() would wrongly use a blocking mechanism internally for some commands which could lead to for example a very long block if the LIST response never showed. The solution was to make sure to properly continue to use the multi interface non-blocking state machine. The new test 1501 verifies the fix. Bug: http://curl.haxx.se/bug/view.cgi?id=3579064 Reported by: Guido Berhoerster Index: curl-7.27.0/lib/ftp.c =================================================================== --- curl-7.27.0.orig/lib/ftp.c +++ curl-7.27.0/lib/ftp.c @@ -650,11 +650,18 @@ static CURLcode ftp_readresp(curl_socket if(ftpcode) *ftpcode = code; - if(421 == code) + if(421 == code) { /* 421 means "Service not available, closing control connection." and FTP * servers use it to signal that idle session timeout has been exceeded. - * If we ignored the response, it could end up hanging in some cases. */ + * If we ignored the response, it could end up hanging in some cases. + * + * This response code can come at any point so having it treated + * generically is a good idea. + */ + infof(data, "We got a 421 - timeout!\n"); + state(conn, FTP_STOP); return CURLE_OPERATION_TIMEDOUT; + } return result; } @@ -2378,6 +2385,7 @@ static CURLcode ftp_state_stor_resp(stru if(ftpcode>=400) { failf(data, "Failed FTP upload: %0d", ftpcode); + state(conn, FTP_STOP); /* oops, we never close the sockets! */ return CURLE_UPLOAD_FAILED; } @@ -2395,9 +2403,6 @@ static CURLcode ftp_state_stor_resp(stru if(!connected) { struct ftp_conn *ftpc = &conn->proto.ftpc; infof(data, "Data conn was not available immediately\n"); - /* as there's not necessarily an immediate action on the control - connection now, we halt the state machine */ - state(conn, FTP_STOP); ftpc->wait_data_conn = TRUE; } @@ -3647,6 +3652,8 @@ static CURLcode ftp_do_more(struct conne /* the ftp struct is inited in ftp_connect() */ struct FTP *ftp = data->state.proto.ftp; + *complete = FALSE; + /* if the second connection isn't done yet, wait for it */ if(!conn->bits.tcpconnect[SECONDARYSOCKET]) { result = Curl_is_connected(conn, SECONDARYSOCKET, &connected); @@ -3659,6 +3666,18 @@ static CURLcode ftp_do_more(struct conne return result; } + if((data->state.used_interface == Curl_if_multi) && + ftpc->state) { + /* multi interface and already in a state so skip the intial commands. + They are only done to kickstart the do_more state */ + result = ftp_multi_statemach(conn, complete); + + /* if we got an error or if we don't wait for a data connection return + immediately */ + if(result || (ftpc->wait_data_conn != TRUE)) + return result; + } + if(ftp->transfer <= FTPTRANSFER_INFO) { /* a transfer is about to take place, or if not a file name was given so we'll do a SIZE on it later and then we need the right TYPE first */ @@ -3712,7 +3731,13 @@ static CURLcode ftp_do_more(struct conne return result; } } - result = ftp_easy_statemach(conn); + if(data->state.used_interface == Curl_if_multi) { + result = ftp_multi_statemach(conn, complete); + + return result; + } + else + result = ftp_easy_statemach(conn); } if((result == CURLE_OK) && (ftp->transfer != FTPTRANSFER_BODY)) @@ -4386,20 +4411,21 @@ CURLcode ftp_parse_url_path(struct conne static CURLcode ftp_dophase_done(struct connectdata *conn, bool connected) { - CURLcode result = CURLE_OK; struct FTP *ftp = conn->data->state.proto.ftp; struct ftp_conn *ftpc = &conn->proto.ftpc; if(connected) { bool completed; - result = ftp_do_more(conn, &completed); - } + CURLcode result = ftp_do_more(conn, &completed); - if(result && (conn->sock[SECONDARYSOCKET] != CURL_SOCKET_BAD)) { - /* Failure detected, close the second socket if it was created already */ - Curl_closesocket(conn, conn->sock[SECONDARYSOCKET]); - conn->sock[SECONDARYSOCKET] = CURL_SOCKET_BAD; - return result; + if(result) { + if(conn->sock[SECONDARYSOCKET] != CURL_SOCKET_BAD) { + /* close the second socket if it was created already */ + Curl_closesocket(conn, conn->sock[SECONDARYSOCKET]); + conn->sock[SECONDARYSOCKET] = CURL_SOCKET_BAD; + } + return result; + } } if(ftp->transfer != FTPTRANSFER_BODY) @@ -4411,7 +4437,7 @@ static CURLcode ftp_dophase_done(struct ftpc->ctl_valid = TRUE; /* seems good */ - return result; + return CURLE_OK; } /* called from multi.c while DOing */ Index: curl-7.27.0/lib/pingpong.c =================================================================== --- curl-7.27.0.orig/lib/pingpong.c +++ curl-7.27.0/lib/pingpong.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2011, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 1998 - 2012, Daniel Stenberg, <daniel@haxx.se>, et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -424,6 +424,9 @@ CURLcode Curl_pp_readresp(curl_socket_t it may actually contain another end of response already! */ clipamount = gotbytes - i; restart = TRUE; + DEBUGF(infof(data, "Curl_pp_readresp_ %d bytes of trailing " + "server response left\n", + (int)clipamount)); } else if(keepon) { Index: curl-7.27.0/tests/data/Makefile.am =================================================================== --- curl-7.27.0.orig/tests/data/Makefile.am +++ curl-7.27.0/tests/data/Makefile.am @@ -93,6 +93,7 @@ test1379 test1380 test1381 test1382 test test1387 test1388 test1389 test1390 test1391 test1392 test1393 \ test1400 test1401 test1402 test1403 test1404 test1405 test1406 test1407 \ test1408 test1409 test1410 \ +test1501 \ test2000 test2001 test2002 test2003 test2004 test2005 test2006 test2007 \ test2008 test2009 test2010 test2011 test2012 test2013 test2014 test2015 \ test2016 test2017 test2018 test2019 test2020 test2021 test2022 Index: curl-7.27.0/tests/data/test1501 =================================================================== --- /dev/null +++ curl-7.27.0/tests/data/test1501 @@ -0,0 +1,53 @@ +<testcase> +<info> +<keywords> +FTP +RETR +multi +LIST +</keywords> +</info> + +# Server-side +<reply> +<data> +</data> +<servercmd> +DELAY LIST 2 +DELAY TYPE 2 +</servercmd> +</reply> + +# Client-side +<client> +<server> +ftp +</server> +<tool> +lib1501 +</tool> + <name> +FTP with multi interface and slow LIST response + </name> + <command> +ftp://%HOSTIP:%FTPPORT/1501/ +</command> +</client> +# Verify data after the test has been "shot" +<verify> +<errorcode> +0 +</errorcode> +<protocol> +USER anonymous +PASS ftp@example.com +PWD +CWD 1501 +EPSV +TYPE A +LIST +QUIT +</protocol> + +</verify> +</testcase> Index: curl-7.27.0/tests/data/test591 =================================================================== --- curl-7.27.0.orig/tests/data/test591 +++ curl-7.27.0/tests/data/test591 @@ -63,8 +63,9 @@ TYPE I STOR 591 QUIT </protocol> +# CURLE_UPLOAD_FAILED = 25 <errorcode> -10 +25 </errorcode> <upload> </upload> Index: curl-7.27.0/tests/data/test592 =================================================================== --- curl-7.27.0.orig/tests/data/test592 +++ curl-7.27.0/tests/data/test592 @@ -52,6 +52,7 @@ Moooooooooooo for 592 s/^PORT (.*)/PORT/ s/^EPRT \|1\|(.*)/EPRT \|1\|/ </strippart> +# a 421 response must prevent further commands from being sent <protocol> USER anonymous PASS ftp@example.com @@ -61,10 +62,10 @@ EPRT |1| PORT TYPE I STOR 592 -QUIT </protocol> +# 28 == CURLE_OPERATION_TIMEDOUT <errorcode> -10 +28 </errorcode> <upload> </upload> Index: curl-7.27.0/tests/libtest/lib1501.c =================================================================== --- /dev/null +++ curl-7.27.0/tests/libtest/lib1501.c @@ -0,0 +1,126 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2012, Daniel Stenberg, <daniel@haxx.se>, et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ +#include "test.h" + +#include <fcntl.h> + +#include "testutil.h" +#include "warnless.h" +#include "memdebug.h" + +#define TEST_HANG_TIMEOUT 30 * 1000 + +/* 500 milliseconds allowed. An extreme number but lets be really conservative + to allow old and slow machines to run this test too */ +#define MAX_BLOCKED_TIME_US 500000 + +/* return the number of microseconds between two time stamps */ +static int elapsed(struct timeval *before, + struct timeval *after) +{ + ssize_t result; + + result = (after->tv_sec - before->tv_sec) * 1000000 + + after->tv_usec - before->tv_usec; + if (result < 0) + result = 0; + + return curlx_sztosi(result); +} + + +int test(char *URL) +{ + CURL *handle = NULL; + CURLM *mhandle = NULL; + int res = 0; + int still_running = 0; + + start_test_timing(); + + global_init(CURL_GLOBAL_ALL); + + easy_init(handle); + + easy_setopt(handle, CURLOPT_URL, URL); + easy_setopt(handle, CURLOPT_VERBOSE, 1L); + + multi_init(mhandle); + + multi_add_handle(mhandle, handle); + + multi_perform(mhandle, &still_running); + + abort_on_test_timeout(); + + while(still_running) { + struct timeval timeout; + fd_set fdread; + fd_set fdwrite; + fd_set fdexcep; + int maxfd = -99; + struct timeval before; + struct timeval after; + int e; + + timeout.tv_sec = 0; + timeout.tv_usec = 100000L; /* 100 ms */ + + FD_ZERO(&fdread); + FD_ZERO(&fdwrite); + FD_ZERO(&fdexcep); + + multi_fdset(mhandle, &fdread, &fdwrite, &fdexcep, &maxfd); + + /* At this point, maxfd is guaranteed to be greater or equal than -1. */ + + select_test(maxfd+1, &fdread, &fdwrite, &fdexcep, &timeout); + + abort_on_test_timeout(); + + fprintf(stderr, "ping\n"); + gettimeofday(&before, 0); + + multi_perform(mhandle, &still_running); + + abort_on_test_timeout(); + + gettimeofday(&after, 0); + e = elapsed(&before, &after); + fprintf(stderr, "pong = %d\n", e); + + if(e > MAX_BLOCKED_TIME_US) { + res = 100; + break; + } + } + +test_cleanup: + + /* undocumented cleanup sequence - type UA */ + + curl_multi_cleanup(mhandle); + curl_easy_cleanup(handle); + curl_global_cleanup(); + + return res; +} -- To unsubscribe, e-mail: opensuse-commit+unsubscribe@opensuse.org For additional commands, e-mail: opensuse-commit+help@opensuse.org