cURL / Mailing Lists / curl-library / Single Mail

curl-library

BUG?: running a SFTP directory listing in a separate thread on Solaris 10 Sparc fails

From: Michael Peltonen <m.a.p.peltonen_at_gmail.com>
Date: Fri, 12 Jun 2009 16:06:52 +0300

Hi all!

I can't run a directory listing in Solaris 10 in any other thread than
the main program thread. The SFTP initialization fails:

Thread 0, gets sftp://example.com/~/ftp/
* About to connect() to example.com port 22 (#0)
* Trying 127.0.0.1... * connected
* Connected to example.com (127.0.0.1) port 22 (#0)
* Failure establishing ssh session
* Closing connection #0
* Failed initialization
Thread 0 terminated

This is the output from the modified multithread application (I made
it to make sure that the bug weren't dependent on the boost::thread
library that I actually use, which I confirmed by this test). The
code:

 /*****************************************************************************
 * _ _ ____ _
 * Project ___| | | | _ \| |
 * / __| | | | |_) | |
 * | (__| |_| | _ <| |___
 * \___|\___/|_| \_\_____|
 *
 * $Id: multithread.c,v 1.4 2008-04-03 20:28:33 danf Exp $
 */

/* A multi-threaded example that uses pthreads extensively to fetch
 * X remote files at once */

#include <stdio.h>
#include <pthread.h>
#include <curl/curl.h>

#define NUMT 1

struct FtpFile {
  const char *filename;
  FILE *stream;
};

size_t my_fwrite(void *buffer, size_t size, size_t nmemb, void *stream)
{
  struct FtpFile *out=(struct FtpFile *)stream;
  if(out && !out->stream) {
    /* open file for writing */
    out->stream=fopen(out->filename, "wb");
    if(!out->stream)
      return -1; /* failure, can't open file to write */
  }
  return fwrite(buffer, size, nmemb, out->stream);
}

/*
  List of URLs to fetch.

  If you intend to use a SSL-based protocol here you MUST setup the OpenSSL
  callback functions as described here:

  http://www.openssl.org/docs/crypto/threads.html#DESCRIPTION

*/
const char * const urls[NUMT]= {
  "sftp://example.com/~/ftp/"
};

static void *pull_one_url(void *url)
{
  CURL *curl;

  struct FtpFile ftpfile={
    "test.txt",
    NULL
  };

  curl = curl_easy_init();
  curl_easy_setopt(curl, CURLOPT_URL, url);
  curl_easy_setopt(curl, CURLOPT_USERPWD, "username:password");
  curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, my_fwrite);
  curl_easy_setopt(curl, CURLOPT_WRITEDATA, &ftpfile);
  curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);

  curl_easy_perform(curl); /* ignores error */
  curl_easy_cleanup(curl);

  return NULL;
}

/*
   int pthread_create(pthread_t *new_thread_ID,
   const pthread_attr_t *attr,
   void * (*start_func)(void *), void *arg);
*/

int main(int argc, char **argv)
{
  pthread_t tid[NUMT];
  int i;
  int error;

  /* Must initialize libcurl before any threads are started */
  curl_global_init(CURL_GLOBAL_ALL);

  for(i=0; i< NUMT; i++) {
    error = pthread_create(&tid[i],
                           NULL, /* default attributes please */
                           pull_one_url,
                           (void *)urls[i]);
    if(0 != error)
      fprintf(stderr, "Couldn't run thread number %d, errno %d\n", i, error);
    else
      fprintf(stderr, "Thread %d, gets %s\n", i, urls[i]);
  }

  /* now wait for all threads to terminate */
  for(i=0; i< NUMT; i++) {
    error = pthread_join(tid[i], NULL);
    fprintf(stderr, "Thread %d terminated\n", i);
  }

  return 0;
}

It works also if I first make a SFTP connection in the main thread and
then all subsequent queries in other threads work.
In windows everything works by default, had no problem with anything,
so I believe this funny behaviour has to do with Solaris threads.

I would appreciate if you can debug and fix this, this bug makes my
program's SFTP features unusable on Solaris,

Michael
Received on 2009-06-12