changed stio_gettime() to use clock_gettime() if available.

enhanced connect timeout handling
This commit is contained in:
hyung-hwan 2016-01-30 19:08:28 +00:00
parent 9b901e924c
commit 15652f70e4
12 changed files with 122 additions and 65 deletions

2
stio/configure vendored
View File

@ -17509,7 +17509,7 @@ _ACEOF
fi fi
done done
for ac_func in timegm timelocal localtime_r gettimeofday settimeofday for ac_func in timegm timelocal localtime_r gettimeofday settimeofday clock_gettime clock_settime
do : do :
as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"

View File

@ -154,7 +154,7 @@ AC_CHECK_FUNCS([wctype iswctype wctrans towctrans])
AC_CHECK_FUNCS([isblank iswblank]) AC_CHECK_FUNCS([isblank iswblank])
AC_CHECK_FUNCS([lseek64 stat64 fstat64 lstat64 ftruncate64 readdir64 dirfd]) AC_CHECK_FUNCS([lseek64 stat64 fstat64 lstat64 ftruncate64 readdir64 dirfd])
AC_CHECK_FUNCS([lstat fchmod fsync ftruncate]) AC_CHECK_FUNCS([lstat fchmod fsync ftruncate])
AC_CHECK_FUNCS([timegm timelocal localtime_r gettimeofday settimeofday]) AC_CHECK_FUNCS([timegm timelocal localtime_r gettimeofday settimeofday clock_gettime clock_settime])
AC_CHECK_FUNCS([utime utimes futimes lutimes futimens]) AC_CHECK_FUNCS([utime utimes futimes lutimes futimens])
AC_CHECK_FUNCS([sysconf prctl fdopendir setrlimit getrlimit getpgid getpgrp]) AC_CHECK_FUNCS([sysconf prctl fdopendir setrlimit getrlimit getpgid getpgrp])
AC_CHECK_FUNCS([backtrace backtrace_symbols]) AC_CHECK_FUNCS([backtrace backtrace_symbols])

View File

@ -161,7 +161,7 @@ int main ()
memset (&sin, 0, STIO_SIZEOF(sin)); memset (&sin, 0, STIO_SIZEOF(sin));
sin.sin_family = AF_INET; sin.sin_family = AF_INET;
memset (&tcp_make, 0, STIO_SIZEOF(&tcp_make));
memcpy (&tcp_make.addr, &sin, STIO_SIZEOF(sin)); memcpy (&tcp_make.addr, &sin, STIO_SIZEOF(sin));
tcp_make.on_sent = tcp_on_sent; tcp_make.on_sent = tcp_on_sent;
tcp_make.on_recv = tcp_on_recv; tcp_make.on_recv = tcp_on_recv;
@ -172,23 +172,28 @@ int main ()
goto oops; goto oops;
} }
{
struct sockaddr_in* p; memset (&sin, 0, STIO_SIZEOF(sin));
p = (struct sockaddr_in*)&tcp_conn.addr; sin.sin_family = AF_INET;
p->sin_family = AF_INET; sin.sin_port = htons(9999);
p->sin_port = htons(9999); //inet_pton (sin.sin_family, "192.168.1.1", &sin.sin_addr);
inet_pton (p->sin_family, "127.0.0.1", &p->sin_addr); inet_pton (sin.sin_family, "127.0.0.1", &sin.sin_addr);
tcp_conn.on_connected = tcp_on_connected;
tcp_conn.on_disconnected = tcp_on_disconnected; memset (&tcp_conn, 0, STIO_SIZEOF(tcp_conn));
//tcp_conn.on_failure = .... (error code? etc???) or on_connect to access success or failure??? what is better?? memcpy (&tcp_conn.addr, &sin, STIO_SIZEOF(sin));
} tcp_conn.timeout.sec = 5;
tcp_conn.on_connected = tcp_on_connected;
tcp_conn.on_disconnected = tcp_on_disconnected;
if (stio_dev_tcp_connect (tcp[0], &tcp_conn) <= -1) if (stio_dev_tcp_connect (tcp[0], &tcp_conn) <= -1)
{ {
printf ("stio_dev_tcp_connect() failed....\n"); printf ("stio_dev_tcp_connect() failed....\n");
goto oops; goto oops;
} }
memset (&sin, 0, STIO_SIZEOF(sin));
sin.sin_family = AF_INET;
sin.sin_port = htons(1234); sin.sin_port = htons(1234);
memset (&tcp_make, 0, STIO_SIZEOF(&tcp_make));
memcpy (&tcp_make.addr, &sin, STIO_SIZEOF(sin)); memcpy (&tcp_make.addr, &sin, STIO_SIZEOF(sin));
tcp_make.on_sent = tcp_on_sent; tcp_make.on_sent = tcp_on_sent;
tcp_make.on_recv = tcp_on_recv; tcp_make.on_recv = tcp_on_recv;

View File

@ -69,6 +69,12 @@
/* Define to 1 if you have the `ceilq' function. */ /* Define to 1 if you have the `ceilq' function. */
#undef HAVE_CEILQ #undef HAVE_CEILQ
/* Define to 1 if you have the `clock_gettime' function. */
#undef HAVE_CLOCK_GETTIME
/* Define to 1 if you have the `clock_settime' function. */
#undef HAVE_CLOCK_SETTIME
/* Define to 1 if you have the `connect' function. */ /* Define to 1 if you have the `connect' function. */
#undef HAVE_CONNECT #undef HAVE_CONNECT

View File

@ -42,8 +42,7 @@
#define STIO_MEMMOVE(dst,src,count) memmove(dst,src,count) #define STIO_MEMMOVE(dst,src,count) memmove(dst,src,count)
#define STIO_ASSERT assert #define STIO_ASSERT assert
typedef struct stio_tmrjob_t stio_tmrjob_t;
typedef stio_size_t stio_tmridx_t;
typedef void (*stio_tmr_handler_t) ( typedef void (*stio_tmr_handler_t) (
stio_t* stio, stio_t* stio,
@ -137,9 +136,10 @@ void stio_cleartmrjobs (
stio_t* stio stio_t* stio
); );
stio_size_t stio_firetmrjobs ( void stio_firetmrjobs (
stio_t* stio, stio_t* stio,
const stio_ntime_t* tm const stio_ntime_t* tm,
stio_size_t* firecnt
); );
int stio_gettmrtmout ( int stio_gettmrtmout (

View File

@ -62,6 +62,7 @@ static int tcp_make (stio_dev_t* dev, void* ctx)
tcp->on_sent = arg->on_sent; tcp->on_sent = arg->on_sent;
tcp->on_recv = arg->on_recv; tcp->on_recv = arg->on_recv;
tcp->tmridx_connect = STIO_TMRIDX_INVALID;
return 0; return 0;
oops: oops:
@ -88,11 +89,17 @@ static void tcp_kill (stio_dev_t* dev)
{ {
stio_dev_tcp_t* tcp = (stio_dev_tcp_t*)dev; stio_dev_tcp_t* tcp = (stio_dev_tcp_t*)dev;
if (tcp->state | (STIO_DEV_TCP_ACCEPTED | STIO_DEV_TCP_CONNECTED)) if (tcp->state & (STIO_DEV_TCP_ACCEPTED | STIO_DEV_TCP_CONNECTED))
{ {
if (tcp->on_disconnected) tcp->on_disconnected (tcp); if (tcp->on_disconnected) tcp->on_disconnected (tcp);
} }
if (tcp->tmridx_connect != STIO_TMRIDX_INVALID)
{
stio_deltmrjob (dev->stio, tcp->tmridx_connect);
STIO_ASSERT (tcp->tmridx_connect == STIO_TMRIDX_INVALID);
}
if (tcp->sck != STIO_SCKHND_INVALID) if (tcp->sck != STIO_SCKHND_INVALID)
{ {
stio_closeasyncsck (tcp->sck); stio_closeasyncsck (tcp->sck);
@ -156,12 +163,16 @@ static void tmr_connect_handle (stio_t* stio, const stio_ntime_t* now, stio_tmrj
* after it gets connected. the timer job doesn't need to be deleted * after it gets connected. the timer job doesn't need to be deleted
* when it gets connected for this check here */ * when it gets connected for this check here */
if (tcp->on_disconnected) tcp->on_disconnected (tcp); if (tcp->on_disconnected) tcp->on_disconnected (tcp);
tcp->state &= ~STIO_DEV_TCP_CONNECTING;
stio_dev_tcp_kill (tcp);
} }
} }
static void tmr_connect_update (stio_t* stio, stio_tmridx_t old_index, stio_tmridx_t new_index, stio_tmrjob_t* job) static void tmr_connect_update (stio_t* stio, stio_tmridx_t old_index, stio_tmridx_t new_index, stio_tmrjob_t* job)
{ {
stio_dev_tcp_t* tcp = (stio_dev_tcp_t*)job->ctx; stio_dev_tcp_t* tcp = (stio_dev_tcp_t*)job->ctx;
tcp->tmridx_connect = new_index;
} }
@ -217,7 +228,6 @@ static int tcp_ioctl (stio_dev_t* dev, int cmd, void* arg)
#else #else
/* the socket is already non-blocking */ /* the socket is already non-blocking */
x = connect (tcp->sck, sa, sl); x = connect (tcp->sck, sa, sl);
if (x == -1) if (x == -1)
{ {
@ -231,11 +241,17 @@ static int tcp_ioctl (stio_dev_t* dev, int cmd, void* arg)
{ {
STIO_MEMSET (&tmrjob, 0, STIO_SIZEOF(tmrjob)); STIO_MEMSET (&tmrjob, 0, STIO_SIZEOF(tmrjob));
tmrjob.ctx = tcp; tmrjob.ctx = tcp;
tmrjob.when = conn->timeout; stio_gettime (&tmrjob.when);
stio_addtime (&tmrjob.when, &conn->timeout, &tmrjob.when);
tmrjob.handler = tmr_connect_handle; tmrjob.handler = tmr_connect_handle;
tmrjob.updater = tmr_connect_update; tmrjob.updater = tmr_connect_update;
if (stio_instmrjob (tcp->stio, &tmrjob) == STIO_TMRIDX_INVALID)
STIO_ASSERT (tcp->tmridx_connect == STIO_TMRIDX_INVALID);
tcp->tmridx_connect = stio_instmrjob (tcp->stio, &tmrjob);
if (tcp->tmridx_connect == STIO_TMRIDX_INVALID)
{ {
stio_dev_event ((stio_dev_t*)tcp, STIO_DEV_EVENT_UPD, STIO_DEV_EVENT_IN);
/* event manipulation failure can't be handled properly. so ignore it */
return -1; return -1;
} }
} }
@ -350,13 +366,18 @@ printf ("TCP READY...%p\n", dev);
tcp->state &= ~STIO_DEV_TCP_CONNECTING; tcp->state &= ~STIO_DEV_TCP_CONNECTING;
tcp->state |= STIO_DEV_TCP_CONNECTED; tcp->state |= STIO_DEV_TCP_CONNECTED;
if (stio_dev_event ((stio_dev_t*)tcp, STIO_DEV_EVENT_UPD, STIO_DEV_EVENT_IN) <= -1)
if (stio_dev_event ((stio_dev_t*)tcp, STIO_DEV_EVENT_UPD, STIO_DEV_EVENT_IN) <= -1) if (stio_dev_event ((stio_dev_t*)tcp, STIO_DEV_EVENT_UPD, STIO_DEV_EVENT_IN) <= -1)
{ {
printf ("CAANOT MANIPULTE EVENT ...\n"); printf ("CAANOT MANIPULTE EVENT ...\n");
return -1; return -1;
} }
if (tcp->tmridx_connect != STIO_TMRIDX_INVALID)
{
stio_deltmrjob (tcp->stio, tcp->tmridx_connect);
STIO_ASSERT (tcp->tmridx_connect == STIO_TMRIDX_INVALID);
}
if (tcp->on_connected (tcp) <= -1) if (tcp->on_connected (tcp) <= -1)
{ {
printf ("ON_CONNECTE HANDLER RETURNEF FAILURE...\n"); printf ("ON_CONNECTE HANDLER RETURNEF FAILURE...\n");
@ -410,6 +431,8 @@ printf ("TCP READY...%p\n", dev);
clitcp->peer = peer; clitcp->peer = peer;
clitcp->parent = tcp; clitcp->parent = tcp;
/* inherit some event handlers from the parent. /* inherit some event handlers from the parent.
* you can still change them inside the on_connected handler */ * you can still change them inside the on_connected handler */
clitcp->on_connected = tcp->on_connected; clitcp->on_connected = tcp->on_connected;
@ -417,6 +440,7 @@ printf ("TCP READY...%p\n", dev);
clitcp->on_sent = tcp->on_sent; clitcp->on_sent = tcp->on_sent;
clitcp->on_recv = tcp->on_recv; clitcp->on_recv = tcp->on_recv;
clitcp->tmridx_connect = STIO_TMRIDX_INVALID;
if (clitcp->on_connected (clitcp) <= -1) stio_dev_tcp_kill (clitcp); if (clitcp->on_connected (clitcp) <= -1) stio_dev_tcp_kill (clitcp);
return 0; /* success but don't invoke on_recv() */ return 0; /* success but don't invoke on_recv() */
} }

View File

@ -62,7 +62,8 @@ struct stio_dev_tcp_t
stio_sckhnd_t sck; stio_sckhnd_t sck;
unsigned int state; /* bitwised-ORed of #stio_dev_tcp_state_t enumerators */
int state;
/* peer address - valid if one of the followings is set: /* peer address - valid if one of the followings is set:
* STIO_DEV_TCP_ACCEPTED * STIO_DEV_TCP_ACCEPTED
@ -81,6 +82,8 @@ struct stio_dev_tcp_t
stio_dev_tcp_on_disconnected_t on_disconnected; stio_dev_tcp_on_disconnected_t on_disconnected;
stio_dev_tcp_on_recv_t on_recv; stio_dev_tcp_on_recv_t on_recv;
stio_dev_tcp_on_sent_t on_sent; stio_dev_tcp_on_sent_t on_sent;
stio_tmridx_t tmridx_connect;
}; };
typedef struct stio_dev_tcp_make_t stio_dev_tcp_make_t; typedef struct stio_dev_tcp_make_t stio_dev_tcp_make_t;

View File

@ -54,7 +54,7 @@
#define EPOCH_DIFF_SECS ((stio_intptr_t)EPOCH_DIFF_DAYS*24*60*60) #define EPOCH_DIFF_SECS ((stio_intptr_t)EPOCH_DIFF_DAYS*24*60*60)
#endif #endif
int stio_gettime (stio_ntime_t* t) void stio_gettime (stio_ntime_t* t)
{ {
#if defined(_WIN32) #if defined(_WIN32)
SYSTEMTIME st; SYSTEMTIME st;
@ -67,7 +67,7 @@ int stio_gettime (stio_ntime_t* t)
*/ */
GetSystemTime (&st); GetSystemTime (&st);
if (SystemTimeToFileTime (&st, &ft) == FALSE) return -1; SystemTimeToFileTime (&st, &ft); /* this must not fail */
li.LowPart = ft.dwLowDateTime; li.LowPart = ft.dwLowDateTime;
li.HighPart = ft.dwHighDateTime; li.HighPart = ft.dwHighDateTime;
@ -76,11 +76,8 @@ int stio_gettime (stio_ntime_t* t)
t->sec = (li.QuadPart / (STIO_NSECS_PER_SEC / 100)) - EPOCH_DIFF_SECS; t->sec = (li.QuadPart / (STIO_NSECS_PER_SEC / 100)) - EPOCH_DIFF_SECS;
t->nsec = (li.QuadPart % (STIO_NSECS_PER_SEC / 100)) * 100; t->nsec = (li.QuadPart % (STIO_NSECS_PER_SEC / 100)) * 100;
return 0;
#elif defined(__OS2__) #elif defined(__OS2__)
APIRET rc;
DATETIME dt; DATETIME dt;
stio_btime_t bt; stio_btime_t bt;
@ -89,8 +86,8 @@ int stio_gettime (stio_ntime_t* t)
* Maybe, resolution too low as it returns values * Maybe, resolution too low as it returns values
* in seconds. */ * in seconds. */
rc = DosGetDateTime (&dt); DosGetDateTime (&dt);
if (rc != NO_ERROR) return -1; /* DosGetDateTime() never fails. it always returns NO_ERROR */
bt.year = dt.year - STIO_BTIME_YEAR_BASE; bt.year = dt.year - STIO_BTIME_YEAR_BASE;
bt.mon = dt.month - 1; bt.mon = dt.month - 1;
@ -101,8 +98,15 @@ int stio_gettime (stio_ntime_t* t)
/*bt.msec = dt.hundredths * 10;*/ /*bt.msec = dt.hundredths * 10;*/
bt.isdst = -1; /* determine dst for me */ bt.isdst = -1; /* determine dst for me */
if (stio_timelocal (&bt, t) <= -1) return -1; if (stio_timelocal (&bt, t) <= -1)
t->nsec = STIO_MSEC_TO_NSEC(dt.hundredths * 10); {
t->sec = time (STIO_NULL);
t->nsec = 0;
}
else
{
t->nsec = STIO_MSEC_TO_NSEC(dt.hundredths * 10);
}
return 0; return 0;
#elif defined(__DOS__) #elif defined(__DOS__)
@ -123,41 +127,51 @@ int stio_gettime (stio_ntime_t* t)
/*bt.msec = dt.hsecond * 10; */ /*bt.msec = dt.hsecond * 10; */
bt.isdst = -1; /* determine dst for me */ bt.isdst = -1; /* determine dst for me */
if (stio_timelocal (&bt, t) <= -1) return -1; if (stio_timelocal (&bt, t) <= -1)
t->nsec = STIO_MSEC_TO_NSEC(dt.hsecond * 10); {
return 0; t->sec = time (STIO_NULL);
t->nsec = 0;
}
else
{
t->nsec = STIO_MSEC_TO_NSEC(dt.hsecond * 10);
}
#elif defined(macintosh) #elif defined(macintosh)
unsigned long tv; unsigned long tv;
GetDateTime (&tv); GetDateTime (&tv);
t->sec = tv; t->sec = tv;
tv->nsec = 0; tv->nsec = 0;
return 0; #elif defined(HAVE_CLOCK_GETTIME) && defined(CLOCK_REALTIME)
struct timespec ts;
if (clock_gettime (CLOCK_REALTIME, &ts) == -1 && errno == EINVAL)
{
#if defined(HAVE_GETTIMEOFDAY)
struct timeval tv;
gettimeofday (&tv, STIO_NULL);
t->sec = tv.tv_sec;
t->nsec = STIO_USEC_TO_NSEC(tv.tv_usec);
#else
t->sec = time (STIO_NULL);
t->nsec = 0;
#endif
}
t->sec = ts.tv_sec;
t->nsec = ts.tv_nsec;
#elif defined(HAVE_GETTIMEOFDAY) #elif defined(HAVE_GETTIMEOFDAY)
struct timeval tv; struct timeval tv;
int n; gettimeofday (&tv, STIO_NULL);
/* TODO: consider using clock_gettime() if it's avaialble.. -lrt may be needed */
n = gettimeofday (&tv, STIO_NULL);
if (n == -1)
{
/* TODO: set stio->errnum using errno... */
return -1;
}
t->sec = tv.tv_sec; t->sec = tv.tv_sec;
t->nsec = STIO_USEC_TO_NSEC(tv.tv_usec); t->nsec = STIO_USEC_TO_NSEC(tv.tv_usec);
return 0;
#else #else
t->sec = STIO_TIME (STIO_NULL); t->sec = time (STIO_NULL);
t->nsec = 0; t->nsec = 0;
return 0;
#endif #endif
} }

View File

@ -106,7 +106,7 @@ extern "C" {
/** /**
* The stio_gettime() function gets the current time. * The stio_gettime() function gets the current time.
*/ */
STIO_EXPORT int stio_gettime ( STIO_EXPORT void stio_gettime (
stio_ntime_t* nt stio_ntime_t* nt
); );

View File

@ -172,35 +172,35 @@ stio_tmridx_t stio_updtmrjob (stio_t* stio, stio_size_t index, const stio_tmrjob
return YOUNGER_THAN(job, &item)? sift_up (stio, index, 0): sift_down (stio, index, 0); return YOUNGER_THAN(job, &item)? sift_up (stio, index, 0): sift_down (stio, index, 0);
} }
stio_size_t stio_firetmrjobs (stio_t* stio, const stio_ntime_t* tm) void stio_firetmrjobs (stio_t* stio, const stio_ntime_t* tm, stio_size_t* firecnt)
{ {
stio_ntime_t now; stio_ntime_t now;
stio_tmrjob_t event; stio_tmrjob_t event;
stio_size_t fire_count = 0; stio_size_t count = 0;
/* if the current time is not specified, get it from the system */ /* if the current time is not specified, get it from the system */
if (tm) now = *tm; if (tm) now = *tm;
else if (stio_gettime (&now) <= -1) return -1; else stio_gettime (&now);
while (stio->tmr.size > 0) while (stio->tmr.size > 0)
{ {
if (stio_cmptime(&stio->tmr.jobs[0].when, &now) > 0) break; if (stio_cmptime(&stio->tmr.jobs[0].when, &now) > 0) break;
event = stio->tmr.jobs[0]; event = stio->tmr.jobs[0];
stio_deltmrjob (stio, 0); /* remove the registered event structure */ stio_deltmrjob (stio, 0); /* remove the registered job */
fire_count++; count++;
event.handler (stio, &now, &event); /* then fire the event */ event.handler (stio, &now, &event); /* then fire the job */
} }
return fire_count; if (firecnt) *firecnt = count;
} }
int stio_gettmrtmout (stio_t* stio, const stio_ntime_t* tm, stio_ntime_t* tmout) int stio_gettmrtmout (stio_t* stio, const stio_ntime_t* tm, stio_ntime_t* tmout)
{ {
stio_ntime_t now; stio_ntime_t now;
/* time-out can't be calculated when there's no event scheduled */ /* time-out can't be calculated when there's no job scheduled */
if (stio->tmr.size <= 0) if (stio->tmr.size <= 0)
{ {
stio->errnum = STIO_ENOENT; stio->errnum = STIO_ENOENT;
@ -209,7 +209,7 @@ int stio_gettmrtmout (stio_t* stio, const stio_ntime_t* tm, stio_ntime_t* tmout)
/* if the current time is not specified, get it from the system */ /* if the current time is not specified, get it from the system */
if (tm) now = *tm; if (tm) now = *tm;
else if (stio_gettime (&now) <= -1) return -1; else stio_gettime (&now);
stio_subtime (&stio->tmr.jobs[0].when, &now, tmout); stio_subtime (&stio->tmr.jobs[0].when, &now, tmout);
if (tmout->sec < 0) stio_cleartime (tmout); if (tmout->sec < 0) stio_cleartime (tmout);

View File

@ -227,15 +227,17 @@ int stio_exec (stio_t* stio)
/*if (!stio->dev.head) return 0;*/ /*if (!stio->dev.head) return 0;*/
/* execute the scheduled jobs before checking devices with the
* multiplexer. the scheduled jobs can safely destroy the devices */
stio_firetmrjobs (stio, STIO_NULL, STIO_NULL);
if (stio_gettmrtmout (stio, STIO_NULL, &tmout) <= -1) if (stio_gettmrtmout (stio, STIO_NULL, &tmout) <= -1)
{ {
/* defaults to 1 second if timeout can't be acquired */ /* defaults to 1 second if timeout can't be acquired */
tmout.sec = 1; tmout.sec = 1; /* TODO: make the default timeout configurable */
tmout.nsec = 0; tmout.nsec = 0;
} }
#if defined(_WIN32) #if defined(_WIN32)
/* /*
if (GetQueuedCompletionStatusEx (stio->iocp, stio->ovls, STIO_COUNTOF(stio->ovls), &nentries, timeout, FALSE) == FALSE) if (GetQueuedCompletionStatusEx (stio->iocp, stio->ovls, STIO_COUNTOF(stio->ovls), &nentries, timeout, FALSE) == FALSE)

View File

@ -29,6 +29,9 @@
#include <stio-cmn.h> #include <stio-cmn.h>
typedef struct stio_tmrjob_t stio_tmrjob_t;
typedef stio_size_t stio_tmridx_t;
struct stio_sckadr_t struct stio_sckadr_t
{ {
int family; int family;