No. Using do {} while() must not change (you add braces) since it
allows the macro to successfully be used as a function in all
circumstances in C code. In this case you would add an outer
do {} while() as such:
Ok, that's fair enough. Changed
I assume you're talking about the spaces between the backslash and the code in the macro? If so, I think I've fixed that now (I didn't notice my editor had done it). If it's something else, can you be more specific so I can fix that as well?Also, please make sure to maintain code style (whitespace changes) in the code that you work on. Thanks!
Btw, it doesn't make sense to have while(1) immediately preceded by a conditional break IMO.
Agreed, changed.
Matt -- _____________________________________________ Matt Lilley Software Engineer SecuritEase Tel: +64 4 912-2100 Fax: +64 4 912-2101 E-mail: [email protected] Web: http://www.securitease.com _____________________________________________ This e-mail has passed our content security scan. It is covered by the confidentiality clauses at http://www.securitease.com/content_and_confidentiality
>From 1af4d98907ac318e0cee8675306a05e4d223de65 Mon Sep 17 00:00:00 2001 From: Matt Lilley <[email protected]> Date: Tue, 3 May 2011 11:20:24 +1200 Subject: [PATCH] Fixes bug #160 as per Daniel's suggestion --- include/libssh2.h | 4 ++++ src/libssh2_priv.h | 3 +++ src/session.c | 51 +++++++++++++++++++++++++++++++++++++++++++++------ src/session.h | 44 +++++++++++++++++++++++--------------------- 4 files changed, 75 insertions(+), 27 deletions(-) diff --git a/include/libssh2.h b/include/libssh2.h index e207411..9462360 100644 --- a/include/libssh2.h +++ b/include/libssh2.h @@ -705,6 +705,10 @@ LIBSSH2_API int libssh2_session_get_blocking(LIBSSH2_SESSION* session); LIBSSH2_API void libssh2_channel_set_blocking(LIBSSH2_CHANNEL *channel, int blocking); +LIBSSH2_API void libssh2_session_set_timeout(LIBSSH2_SESSION* session, + long timeout); +LIBSSH2_API long libssh2_session_get_timeout(LIBSSH2_SESSION* session); + /* libssh2_channel_handle_extended_data is DEPRECATED, do not use! */ LIBSSH2_API void libssh2_channel_handle_extended_data(LIBSSH2_CHANNEL *channel, int ignore_mode); diff --git a/src/libssh2_priv.h b/src/libssh2_priv.h index 231401e..5a697c7 100644 --- a/src/libssh2_priv.h +++ b/src/libssh2_priv.h @@ -559,6 +559,9 @@ struct _LIBSSH2_SESSION /* this is set to TRUE if a blocking API behavior is requested */ int api_block_mode; + /* Timeout used when blocking API behavior is active */ + long api_timeout; + /* Server's public key */ const LIBSSH2_HOSTKEY_METHOD *hostkey; void *server_hostkey_abstract; diff --git a/src/session.c b/src/session.c index e4714e8..edf98d8 100644 --- a/src/session.c +++ b/src/session.c @@ -481,6 +481,7 @@ libssh2_session_init_ex(LIBSSH2_ALLOC_FUNC((*my_alloc)), session->free = local_free; session->realloc = local_realloc; session->abstract = abstract; + session->api_timeout = 0; /* timeout-free API by default */ session->api_block_mode = 1; /* blocking API by default */ _libssh2_debug(session, LIBSSH2_TRACE_TRANS, "New session resource allocated"); @@ -542,11 +543,12 @@ libssh2_session_callback_set(LIBSSH2_SESSION * session, * Utility function that waits for action on the socket. Returns 0 when ready * to run again or error on timeout. */ -int _libssh2_wait_socket(LIBSSH2_SESSION *session) +int _libssh2_wait_socket(LIBSSH2_SESSION *session, time_t start_time) { int rc; int seconds_to_next; int dir; + int has_timeout; /* since libssh2 often sets EAGAIN internally before this function is called, we can decrease some amount of confusion in user programs by @@ -592,8 +594,25 @@ int _libssh2_wait_socket(LIBSSH2_SESSION *session) fd_set *readfd = NULL; struct timeval tv; - tv.tv_sec = seconds_to_next; - tv.tv_usec = 0; + if (seconds_to_next > 0) { + tv.tv_sec = seconds_to_next; + tv.tv_usec = 0; + has_timeout = 1; + } else if (session->api_timeout > 0) { + time_t now = time (NULL); + long elapsed_ms = (long)(1000*difftime(start_time, now)); + if (elapsed_ms > session->api_timeout) { + session->err_code = LIBSSH2_ERROR_TIMEOUT; + return LIBSSH2_ERROR_TIMEOUT; + } + /* Seconds */ + tv.tv_sec = (session->api_timeout - elapsed_ms) / 1000; + /* Microseconds */ + tv.tv_usec = ((session->api_timeout - elapsed_ms) % 1000) * 1000; + has_timeout = 1; + } else { + has_timeout = 0; + } if(dir & LIBSSH2_SESSION_BLOCK_INBOUND) { FD_ZERO(&rfd); @@ -607,10 +626,8 @@ int _libssh2_wait_socket(LIBSSH2_SESSION *session) writefd = &wfd; } - /* Note that this COULD be made to use a timeout that perhaps - could be customizable by the app or something... */ rc = select(session->socket_fd + 1, readfd, writefd, NULL, - seconds_to_next ? &tv : NULL); + has_timeout ? &tv : NULL); #endif } } @@ -1281,6 +1298,28 @@ libssh2_session_get_blocking(LIBSSH2_SESSION * session) return session->api_block_mode; } + +/* libssh2_session_set_timeout + * + * Set a session's timeout (in msec) for blocking mode, + * or 0 to disable timeouts. + */ +LIBSSH2_API void +libssh2_session_set_timeout(LIBSSH2_SESSION * session, long timeout) +{ + session->api_timeout = timeout; +} + +/* libssh2_session_get_timeout + * + * Returns a session's timeout, or 0 if disabled + */ +LIBSSH2_API long +libssh2_session_get_timeout(LIBSSH2_SESSION * session) +{ + return session->api_timeout; +} + /* * libssh2_poll_channel_read * diff --git a/src/session.h b/src/session.h index 4eac3a6..aa022fb 100644 --- a/src/session.h +++ b/src/session.h @@ -53,15 +53,16 @@ */ #define BLOCK_ADJUST(rc,sess,x) \ do { \ - rc = x; \ - /* the order of the check below is important to properly deal with the - case when the 'sess' is freed */ \ - if((rc != LIBSSH2_ERROR_EAGAIN) || !sess->api_block_mode) \ - break; \ - rc = _libssh2_wait_socket(sess); \ - if(rc) \ - break; \ - } while(1) + time_t entry_time = time (NULL); \ + do { \ + rc = x; \ + /* the order of the check below is important to properly deal with the + case when the 'sess' is freed */ \ + if((rc != LIBSSH2_ERROR_EAGAIN) || !sess->api_block_mode) \ + break; \ + rc = _libssh2_wait_socket(sess, entry_time); \ + } while(rc); \ + } while(0) /* * For functions that returns a pointer, we need to check if the API is @@ -69,21 +70,22 @@ * immediately. If the API is blocking and we get a NULL we check the errno * and *only* if that is EAGAIN we loop and wait for socket action. */ -#define BLOCK_ADJUST_ERRNO(ptr,sess,x) \ +#define BLOCK_ADJUST_ERRNO(ptr,sess,x) \ do { \ - int rc; \ - ptr = x; \ - if(!sess->api_block_mode || \ - (ptr != NULL) || \ - (libssh2_session_last_errno(sess) != LIBSSH2_ERROR_EAGAIN) ) \ - break; \ - rc = _libssh2_wait_socket(sess); \ - if(rc) \ - break; \ - } while(1) + time_t entry_time = time (NULL); \ + do { \ + int rc; \ + ptr = x; \ + if(!sess->api_block_mode || \ + (ptr != NULL) || \ + (libssh2_session_last_errno(sess) != LIBSSH2_ERROR_EAGAIN) ) \ + break; \ + rc = _libssh2_wait_socket(sess, entry_time); \ + } while(!rc); \ + } while(0) -int _libssh2_wait_socket(LIBSSH2_SESSION *session); +int _libssh2_wait_socket(LIBSSH2_SESSION *session, time_t entry_time); /* this is the lib-internal set blocking function */ int _libssh2_session_set_blocking(LIBSSH2_SESSION * session, int blocking); -- 1.7.2.3.msysgit.0
_______________________________________________ libssh2-devel http://cool.haxx.se/cgi-bin/mailman/listinfo/libssh2-devel
