From d6c8bd4a1b5a71bf730f20947a153d6d24b74615 Mon Sep 17 00:00:00 2001 From: hyung-hwan Date: Sat, 28 Jul 2012 14:43:59 +0000 Subject: [PATCH] added more timeout handling code --- qse/doc/page/awk.doc | 21 ++++++++ qse/lib/awk/std.c | 8 +++- qse/lib/cmn/nwio.c | 112 ++++++++++++++++++++----------------------- 3 files changed, 79 insertions(+), 62 deletions(-) diff --git a/qse/doc/page/awk.doc b/qse/doc/page/awk.doc index 3e1e84f7..541a704f 100644 --- a/qse/doc/page/awk.doc +++ b/qse/doc/page/awk.doc @@ -277,6 +277,27 @@ BEGIN { } @endcode +You can specify TCP or UDP timeouts for connection, accepting, reading, and +writing with setioattr (pipe-name, timeout-name, timeout-value). timeout-name +should be one of "ctimeout", "atimeout", "rtimeout", and "wtimeout". +timeout-value is a number specifying the actual timeout in milliseconds. +A negative value indicates no timeout. + +You can call getioattr (pipe-name, timeout-name) to get the current +timeout-value set. + +See the example below. + +@code +BEGIN { + setioattr ("tcp://127.0.0.1:9999", "ctimeout", 3000); + setioattr ("tcp://127.0.0.1:9999", "rtimeout", 5000); + print "hello world" || "tcp://127.0.0.1:9999"; + "tcp://127.0.0.1:9999" || getline x; + print x; +} +@endcode + @subsection awk_ext_return RETURN The return statement is valid in BEGIN blocks, END blocks, and pattern-action blocks as well as in functions. The execution of a calling block is aborted diff --git a/qse/lib/awk/std.c b/qse/lib/awk/std.c index 951b877d..18d0a046 100644 --- a/qse/lib/awk/std.c +++ b/qse/lib/awk/std.c @@ -126,7 +126,7 @@ typedef struct ioattr_t { qse_cmgr_t* cmgr; qse_char_t cmgr_name[64]; /* i assume that the cmgr name never exceeds this length */ - qse_long_t tmout[4]; + int tmout[4]; } ioattr_t; static ioattr_t* get_ioattr (qse_htb_t* tab, const qse_char_t* ptr, qse_size_t len); @@ -1848,6 +1848,12 @@ static int fnc_setioattr (qse_awk_rtx_t* rtx, const qse_cstr_t* fnm) * parameter is 0. so i don't check for an error */ x = qse_awk_rtx_strtonum (rtx, 0, ptr[2], len[2], &l, &r); if (x >= 1) l = (qse_long_t)r; + + if (l < QSE_TYPE_MIN(int) || l > QSE_TYPE_MAX(int)) + { + fret = -1; + goto done; + } pair = find_or_make_ioattr (rtx, &rxtn->cmgrtab, ptr[0], len[0]); if (pair == QSE_NULL) diff --git a/qse/lib/cmn/nwio.c b/qse/lib/cmn/nwio.c index d27b0000..92dfb385 100644 --- a/qse/lib/cmn/nwio.c +++ b/qse/lib/cmn/nwio.c @@ -250,6 +250,36 @@ static qse_nwio_errnum_t tio_errnum_to_nwio_errnum (qse_tio_t* tio) } } +static int wait_for_data (qse_nwio_t* nwio, int tmout, int what) +{ + int xret; + fd_set fds[2]; + struct timeval tv; + + FD_ZERO (&fds[0]); + FD_ZERO (&fds[1]); + + FD_SET (nwio->handle, &fds[what]); + + tv.tv_sec = tmout / QSE_MSECS_PER_SEC; + tv.tv_usec = (tmout % QSE_MSECS_PER_SEC) * + QSE_USECS_PER_MSEC; + + xret = select (nwio->handle + 1, &fds[0], &fds[1], QSE_NULL, &tv); + if (xret <= -1) + { + nwio->errnum = syserr_to_errnum (errno); + return -1; + } + else if (xret == 0) + { + nwio->errnum = QSE_NWIO_ETMOUT; + return -1; + } + + return 0; +} + qse_nwio_t* qse_nwio_open ( qse_mmgr_t* mmgr, qse_size_t xtnsize, const qse_nwad_t* nwad, int flags, const qse_nwio_tmout_t* tmout) @@ -499,6 +529,9 @@ int qse_nwio_init ( goto oops; } + if (nwio->tmout.a >= 0 && + wait_for_data (nwio, nwio->tmout.a, 0) <= -1) goto oops; + handle = accept (nwio->handle, (struct sockaddr*)&addr, &addrlen); if (handle <= -1) { @@ -533,9 +566,6 @@ int qse_nwio_init ( if (nwio->tmout.c >= 0 && (flags & QSE_NWIO_TCP)) { - fd_set wfds; - struct timeval tv; - if ((xret <= -1 && errno != EINPROGRESS) || fcntl (nwio->handle, F_SETFL, orgfl) <= -1) { @@ -543,29 +573,7 @@ int qse_nwio_init ( goto oops; } - FD_ZERO (&wfds); - FD_SET (nwio->handle, &wfds); - tv.tv_sec = nwio->tmout.c / QSE_MSECS_PER_SEC; - tv.tv_usec = (nwio->tmout.c % QSE_MSECS_PER_SEC) * - QSE_USECS_PER_MSEC; - - xret = select (nwio->handle + 1, - QSE_NULL, &wfds, QSE_NULL, &tv); - if (xret <= -1) - { - nwio->errnum = syserr_to_errnum (errno); - goto oops; - } - else if (xret == 0) - { - nwio->errnum = QSE_NWIO_ETMOUT; - goto oops; - } - else if (!FD_ISSET (nwio->handle, &wfds)) - { - nwio->errnum = QSE_NWIO_ECONN; - goto oops; - } + if (wait_for_data (nwio, nwio->tmout.c, 1) <= -1) goto oops; else { #if defined(HAVE_SOCKLEN_T) @@ -573,6 +581,7 @@ int qse_nwio_init ( #else int xlen; #endif + xlen = QSE_SIZEOF(xret); if (getsockopt (nwio->handle, SOL_SOCKET, SO_ERROR, (char*)&xret, &xlen) <= -1) { nwio->errnum = syserr_to_errnum (errno); @@ -724,33 +733,6 @@ void qse_nwio_purge (qse_nwio_t* nwio) if (nwio->tio) qse_tio_purge (nwio->tio); } -static int wait_for_data (qse_nwio_t* nwio, int tmout, int what) -{ - int xret; - fd_set fds[2]; - struct timeval tv; - - FD_ZERO (&fds[0]); - FD_ZERO (&fds[1]); - FD_SET (nwio->handle, &fds[what]); - tv.tv_sec = tmout / QSE_MSECS_PER_SEC; - tv.tv_usec = (tmout % QSE_MSECS_PER_SEC) * - QSE_USECS_PER_MSEC; - - xret = select (nwio->handle + 1, &fds[0], &fds[1], QSE_NULL, &tv); - if (xret <= -1) - { - nwio->errnum = syserr_to_errnum (errno); - return -1; - } - else if (xret == 0) - { - nwio->errnum = QSE_NWIO_ETMOUT; - return -1; - } - - return 0; -} /* ---------------------------------------------------------- */ static qse_ssize_t nwio_read (qse_nwio_t* nwio, void* buf, qse_size_t size) @@ -860,10 +842,15 @@ reread: #endif addrlen = QSE_SIZEOF(addr); - /* it's similar to accept for tcp. - * since i'm expecting the first sender and call - * connect() to it below. - * TODO: do i have apply tmout.a instead of tmout.r??? */ + + /* it's similar to accept for tcp because i'm expecting + * the first sender and call connect() to it below just + * like the 'nc' utility does. + * so i treat this recvfrom() as if it is accept(). + */ + if (nwio->tmout.a >= 0 && + wait_for_data (nwio, nwio->tmout.a, 0) <= -1) return -1; + n = recvfrom ( nwio->handle, buf, size, 0, (struct sockaddr*)&addr, &addrlen); @@ -894,10 +881,8 @@ reread: } else { - if (nwio->tmout.r >= 0) - { - if (wait_for_data (nwio, nwio->tmout.r, 0) <= -1) return -1; - } + if (nwio->tmout.r >= 0 && + wait_for_data (nwio, nwio->tmout.r, 0) <= -1) return -1; n = recv (nwio->handle, buf, size, 0); if (n <= -1) @@ -977,6 +962,9 @@ static qse_ssize_t nwio_write (qse_nwio_t* nwio, const void* data, qse_size_t si size = QSE_TYPE_MAX(qse_ssize_t) & QSE_TYPE_MAX(size_t); rewrite: + if (nwio->tmout.w >= 0 && + wait_for_data (nwio, nwio->tmout.w, 1) <= -1) return -1; + n = send (nwio->handle, data, size, 0); if (n <= -1) { @@ -999,7 +987,9 @@ rewrite: qse_ssize_t qse_nwio_write (qse_nwio_t* nwio, const void* data, qse_size_t size) { if (nwio->tio == QSE_NULL) + { return nwio_write (nwio, data, size); + } else { qse_ssize_t n;