예제 #1
0
static bool init_gethostbyname_thread (struct connectdata *conn,
                                       const char *hostname, int port)
{
  struct thread_data *td = malloc(sizeof(*td));

  if (!td) {
    SetLastError(ENOMEM);
    return (0);
  }

  memset (td, 0, sizeof(*td));
  Curl_safefree(conn->async.hostname);
  conn->async.hostname = strdup(hostname);
  if (!conn->async.hostname) {
    free(td);
    SetLastError(ENOMEM);
    return (0);
  }

  conn->async.port = port;
  conn->async.done = FALSE;
  conn->async.status = 0;
  conn->async.dns = NULL;
  conn->async.os_specific = (void*) td;

  td->thread_hnd = CreateThread(NULL, 0, gethostbyname_thread,
                                conn, 0, &td->thread_id);
  if (!td->thread_hnd) {
     TRACE(("CreateThread() failed; %lu\n", GetLastError()));
     destroy_thread_data(conn);
     return (0);
  }
  return (1);
}
예제 #2
0
/* called to check if the name is resolved now */
CURLcode Curl_wait_for_resolv(struct connectdata *conn,
                              struct Curl_dns_entry **entry)
{
  struct thread_data   *td = (struct thread_data*) conn->async.os_specific;
  struct SessionHandle *data = conn->data;
  long   timeout;
  DWORD  status, ticks;
  CURLcode rc;

  curlassert (conn && td);

  /* now, see if there's a connect timeout or a regular timeout to
     use instead of the default one */
  timeout = conn->data->set.connecttimeout ? conn->data->set.connecttimeout :
            conn->data->set.timeout        ? conn->data->set.timeout :
            300;   /* default name resolve timeout in seconds */
  ticks = GetTickCount();

  status = WaitForSingleObject(td->thread_hnd, 1000UL*timeout);
  if (status == WAIT_OBJECT_0 || status == WAIT_ABANDONED) {
     /* Thread finished before timeout; propagate Winsock error to this thread */
     WSASetLastError(conn->async.status);
     GetExitCodeThread(td->thread_hnd, &td->thread_status);
     TRACE(("status %lu, thread-status %08lX\n", status, td->thread_status));
  }
  else {
     conn->async.done = TRUE;
     TerminateThread(td->thread_hnd, (DWORD)-1);
     td->thread_status = (DWORD)-1;
  }

  TRACE(("gethostbyname_thread() retval %08lX, elapsed %lu ms\n",
         td->thread_status, GetTickCount()-ticks));

  if(entry)
    *entry = conn->async.dns;

  rc = CURLE_OK;

  if (!conn->async.dns) {
    /* a name was not resolved */
    if (td->thread_status == (DWORD)-1 || conn->async.status == NO_DATA) {
      failf(data, "Resolving host timed out: %s", conn->name);
      rc = CURLE_OPERATION_TIMEDOUT;
    }
    else if(conn->async.done) {
      failf(data, "Could not resolve host: %s (code %lu)", conn->name, conn->async.status);
      rc = CURLE_COULDNT_RESOLVE_HOST;
    }
    else
      rc = CURLE_OPERATION_TIMEDOUT;

    destroy_thread_data(conn);
    /* close the connection, since we can't return failure here without
       cleaning up this connection properly */
    Curl_disconnect(conn);
  }
  return (rc);
}
예제 #3
0
/*
 * init_resolve_thread() starts a new thread that performs the actual
 * resolve. This function returns before the resolve is done.
 *
 * Returns FALSE in case of failure, otherwise TRUE.
 */
static bool init_resolve_thread (struct connectdata *conn,
                                 const char *hostname, int port,
                                 const Curl_addrinfo *hints)
{
  struct thread_data *td = calloc(sizeof(*td), 1);

  if (!td) {
    SetLastError(ENOMEM);
    return FALSE;
  }

  Curl_safefree(conn->async.hostname);
  conn->async.hostname = strdup(hostname);
  if (!conn->async.hostname) {
    free(td);
    SetLastError(ENOMEM);
    return FALSE;
  }

  conn->async.port = port;
  conn->async.done = FALSE;
  conn->async.status = 0;
  conn->async.dns = NULL;
  conn->async.os_specific = (void*) td;

  td->dummy_sock = CURL_SOCKET_BAD;
  td->stderr_file = stderr;
  td->thread_hnd = (HANDLE) _beginthreadex(NULL, 0, THREAD_FUNC,
                                           conn, 0, &td->thread_id);
#ifdef CURLRES_IPV6
  curlassert(hints);
  td->hints = *hints;
#else
  (void) hints;
#endif

  if (!td->thread_hnd) {
     SetLastError(errno);
     TRACE(("_beginthreadex() failed; %s\n", Curl_strerror(conn,errno)));
     destroy_thread_data(&conn->async);
     return FALSE;
  }
  /* This socket is only to keep Curl_fdset() and select() happy; should never
   * become signalled for read/write since it's unbound but Windows needs
   * atleast 1 socket in select().
   */
  td->dummy_sock = socket(AF_INET, SOCK_DGRAM, 0);
  return TRUE;
}
예제 #4
0
static void
thread_exit_handler(void)
{
    lc_thread_t *thr = get_my_locked_locks();
    if (thr) {
	if (thr->locked.first) {
	    erts_fprintf(stderr,
			 "Thread exiting while having locked locks!\n");
	    print_curr_locks(thr);
	    lc_abort();
	}
	destroy_thread_data(thr);
	/* erts_tsd_set(locks_key, NULL); */
    }
}
예제 #5
0
/*
 * Curl_is_resolved() is called repeatedly to check if a previous name resolve
 * request has completed. It should also make sure to time-out if the
 * operation seems to take too long.
 */
CURLcode Curl_is_resolved( struct connectdata *conn,
						   struct Curl_dns_entry **entry ) {
	*entry = NULL;

	if ( conn->async.done ) {
		/* we're done */
		destroy_thread_data( &conn->async );
		if ( !conn->async.dns ) {
			TRACE( ( "Curl_is_resolved(): CURLE_COULDNT_RESOLVE_HOST\n" ) );
			return CURLE_COULDNT_RESOLVE_HOST;
		}
		*entry = conn->async.dns;
		TRACE( ( "resolved okay, dns %p\n", *entry ) );
	} else {
		TRACE( ( "not yet\n" ) );
	}
	return CURLE_OK;
}
void
client_main(unsigned short      port, 
            int	                connections, 
            const char *        hostName)
{
	int			i;
	SECStatus	secStatus;
	PRStatus    prStatus;
	PRInt32     rv;
	PRNetAddr	addr;
	PRHostEnt   hostEntry;
	char        buffer[PR_NETDB_BUF_SIZE];

	/* Setup network connection. */
	prStatus = PR_GetHostByName(hostName, buffer, sizeof(buffer), &hostEntry);
	if (prStatus != PR_SUCCESS) {
		exitErr("PR_GetHostByName");
	}

	rv = PR_EnumerateHostEnt(0, &hostEntry, port, &addr);
	if (rv < 0) {
		exitErr("PR_EnumerateHostEnt");
	}

	secStatus = launch_thread(&threadMGR, do_connects, &addr, 1);
	if (secStatus != SECSuccess) {
		exitErr("launch_thread");
	}

	if (connections > 1) {
		/* wait for the first connection to terminate, then launch the rest. */
		reap_threads(&threadMGR);
		/* Start up the connections */
		for (i = 2; i <= connections; ++i) {
			secStatus = launch_thread(&threadMGR, do_connects, &addr, i);
			if (secStatus != SECSuccess) {
				errWarn("launch_thread");
			}
		}
	}

	reap_threads(&threadMGR);
	destroy_thread_data(&threadMGR);
}
예제 #7
0
/*
 * Curl_wait_for_resolv() waits for a resolve to finish. This function should
 * be avoided since using this risk getting the multi interface to "hang".
 *
 * If 'entry' is non-NULL, make it point to the resolved dns entry
 *
 * This is the version for resolves-in-a-thread.
 */
CURLcode Curl_wait_for_resolv(struct connectdata *conn,
                              struct Curl_dns_entry **entry)
{
  struct thread_data   *td = (struct thread_data*) conn->async.os_specific;
  struct SessionHandle *data = conn->data;
  long   timeout;
  DWORD  status, ticks;
  CURLcode rc;

  curlassert (conn && td);

  /* now, see if there's a connect timeout or a regular timeout to
     use instead of the default one */
  timeout =
    conn->data->set.connecttimeout ? conn->data->set.connecttimeout :
    conn->data->set.timeout ? conn->data->set.timeout :
    CURL_TIMEOUT_RESOLVE; /* default name resolve timeout */
  ticks = GetTickCount();
  (void)ticks;

  status = WaitForSingleObject(td->thread_hnd, 1000UL*timeout);
  if (status == WAIT_OBJECT_0 || status == WAIT_ABANDONED) {
     /* Thread finished before timeout; propagate Winsock error to this thread.
      * 'conn->async.done = TRUE' is set in Curl_addrinfo4/6_callback().
      */
     WSASetLastError(conn->async.status);
     GetExitCodeThread(td->thread_hnd, &td->thread_status);
     TRACE(("%s() status %lu, thread retval %lu, ",
            THREAD_NAME, status, td->thread_status));
  }
  else {
     conn->async.done = TRUE;
     td->thread_status = (DWORD)-1;
     TRACE(("%s() timeout, ", THREAD_NAME));
  }

  TRACE(("elapsed %lu ms\n", GetTickCount()-ticks));

  CloseHandle(td->thread_hnd);

  if(entry)
    *entry = conn->async.dns;

  rc = CURLE_OK;

  if (!conn->async.dns) {
    /* a name was not resolved */
    if (td->thread_status == (DWORD)-1 || conn->async.status == NO_DATA) {
      failf(data, "Resolving host timed out: %s", conn->host.name);
      rc = CURLE_OPERATION_TIMEDOUT;
    }
    else if(conn->async.done) {
      failf(data, "Could not resolve host: %s; %s",
            conn->host.name, Curl_strerror(conn,conn->async.status));
      rc = CURLE_COULDNT_RESOLVE_HOST;
    }
    else
      rc = CURLE_OPERATION_TIMEDOUT;
  }

  destroy_thread_data(&conn->async);

  if(CURLE_OK != rc)
    /* close the connection, since we must not return failure from here
       without cleaning up this connection properly */
    Curl_disconnect(conn);

  return (rc);
}
예제 #8
0
/*
 * Curl_wait_for_resolv() waits for a resolve to finish. This function should
 * be avoided since using this risk getting the multi interface to "hang".
 *
 * If 'entry' is non-NULL, make it point to the resolved dns entry
 *
 * This is the version for resolves-in-a-thread.
 */
CURLcode Curl_wait_for_resolv( struct connectdata *conn,
							   struct Curl_dns_entry **entry ) {
	struct thread_data   *td = (struct thread_data*) conn->async.os_specific;
	struct SessionHandle *data = conn->data;
	long timeout;
	DWORD status, ticks;
	CURLcode rc;

	curlassert( conn && td );

	/* now, see if there's a connect timeout or a regular timeout to
	   use instead of the default one */
	timeout =
		conn->data->set.connecttimeout ? conn->data->set.connecttimeout :
		conn->data->set.timeout ? conn->data->set.timeout :
		CURL_TIMEOUT_RESOLVE; /* default name resolve timeout */
	ticks = GetTickCount();

	/* wait for the thread to resolve the name */
	status = WaitForSingleObject( td->event_resolved, 1000UL * timeout );

	/* mark that we are now done waiting */
	ReleaseMutex( td->mutex_waiting );

	/* close our handle to the mutex, no point in hanging on to it */
	CloseHandle( td->mutex_waiting );
	td->mutex_waiting = NULL;

	/* close the event handle, it's useless now */
	CloseHandle( td->event_resolved );
	td->event_resolved = NULL;

	/* has the resolver thread succeeded in resolving our query ? */
	if ( status == WAIT_OBJECT_0 ) {
		/* wait for the thread to exit, it's in the callback sequence */
		if ( WaitForSingleObject( td->thread_hnd, 5000 ) == WAIT_TIMEOUT ) {
			TerminateThread( td->thread_hnd, 0 );
			conn->async.done = TRUE;
			td->thread_status = (DWORD)-1;
			TRACE( ( "%s() thread stuck?!, ", THREAD_NAME ) );
		} else {
			/* Thread finished before timeout; propagate Winsock error to this thread.
			 * 'conn->async.done = TRUE' is set in Curl_addrinfo4/6_callback().
			 */
			WSASetLastError( conn->async.status );
			GetExitCodeThread( td->thread_hnd, &td->thread_status );
			TRACE( ( "%s() status %lu, thread retval %lu, ",
					 THREAD_NAME, status, td->thread_status ) );
		}
	} else {
		conn->async.done = TRUE;
		td->thread_status = (DWORD)-1;
		TRACE( ( "%s() timeout, ", THREAD_NAME ) );
	}

	TRACE( ( "elapsed %lu ms\n", GetTickCount() - ticks ) );

	CloseHandle( td->thread_hnd );

	if ( entry ) {
		*entry = conn->async.dns;
	}

	rc = CURLE_OK;

	if ( !conn->async.dns ) {
		/* a name was not resolved */
		if ( td->thread_status == (DWORD)-1 || conn->async.status == NO_DATA ) {
			failf( data, "Resolving host timed out: %s", conn->host.name );
			rc = CURLE_OPERATION_TIMEDOUT;
		} else if ( conn->async.done )      {
			failf( data, "Could not resolve host: %s; %s",
				   conn->host.name, Curl_strerror( conn,conn->async.status ) );
			rc = CURLE_COULDNT_RESOLVE_HOST;
		} else {
			rc = CURLE_OPERATION_TIMEDOUT;
		}
	}

	destroy_thread_data( &conn->async );

	if ( CURLE_OK != rc ) {
		/* close the connection, since we must not return failure from here
		   without cleaning up this connection properly */
		Curl_disconnect( conn );
	}

	return ( rc );
}