Merged revisions 166297 via svnmerge from
authorRussell Bryant <russell@russellbryant.com>
Mon, 22 Dec 2008 17:29:10 +0000 (17:29 +0000)
committerRussell Bryant <russell@russellbryant.com>
Mon, 22 Dec 2008 17:29:10 +0000 (17:29 +0000)
https://origsvn.digium.com/svn/asterisk/branches/1.4

........
r166297 | russell | 2008-12-22 11:22:56 -0600 (Mon, 22 Dec 2008) | 2 lines

Fix up timeout handling in ast_carefulwrite().

........

git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@166317 65c4cc65-6c06-0410-ace0-fbb531ad65f3

main/utils.c

index 5625285..61638f9 100644 (file)
@@ -1064,9 +1064,11 @@ static int ast_wait_for_output(int fd, int timeoutms)
                .events = POLLOUT,
        };
        int res;
                .events = POLLOUT,
        };
        int res;
+       struct timeval start = ast_tvnow();
+       int elapsed = 0;
 
        /* poll() until the fd is writable without blocking */
 
        /* poll() until the fd is writable without blocking */
-       while ((res = poll(&pfd, 1, timeoutms)) <= 0) {
+       while ((res = poll(&pfd, 1, timeoutms - elapsed)) <= 0) {
                if (res == 0) {
                        /* timed out. */
                        ast_log(LOG_NOTICE, "Timed out trying to write\n");
                if (res == 0) {
                        /* timed out. */
                        ast_log(LOG_NOTICE, "Timed out trying to write\n");
@@ -1075,6 +1077,10 @@ static int ast_wait_for_output(int fd, int timeoutms)
                        /* poll() returned an error, check to see if it was fatal */
 
                        if (errno == EINTR || errno == EAGAIN) {
                        /* poll() returned an error, check to see if it was fatal */
 
                        if (errno == EINTR || errno == EAGAIN) {
+                               elapsed = ast_tvdiff_ms(ast_tvnow(), start);
+                               if (elapsed >= timeoutms) {
+                                       return -1;
+                               }
                                /* This was an acceptable error, go back into poll() */
                                continue;
                        }
                                /* This was an acceptable error, go back into poll() */
                                continue;
                        }
@@ -1084,6 +1090,10 @@ static int ast_wait_for_output(int fd, int timeoutms)
 
                        return -1;
                }
 
                        return -1;
                }
+               elapsed = ast_tvdiff_ms(ast_tvnow(), start);
+               if (elapsed >= timeoutms) {
+                       return -1;
+               }
        }
 
        return 0;
        }
 
        return 0;
@@ -1097,19 +1107,15 @@ static int ast_wait_for_output(int fd, int timeoutms)
  * have a need to wait.  This way, we get better performance.
  * If the descriptor is blocking, all assumptions on the guaranteed
  * detail do not apply anymore.
  * have a need to wait.  This way, we get better performance.
  * If the descriptor is blocking, all assumptions on the guaranteed
  * detail do not apply anymore.
- * Also note that in the current implementation, the delay is per-write,
- * so you still have no guarantees, anyways.
- * Fortunately the routine is only used in a few places (cli.c, manager.c,
- * res_agi.c) so it is reasonably easy to check how it behaves there.
- *
- * XXX We either need to fix the code, or fix the documentation.
  */
 int ast_carefulwrite(int fd, char *s, int len, int timeoutms) 
 {
  */
 int ast_carefulwrite(int fd, char *s, int len, int timeoutms) 
 {
+       struct timeval start = ast_tvnow();
        int res = 0;
        int res = 0;
+       int elapsed = 0;
 
        while (len) {
 
        while (len) {
-               if (ast_wait_for_output(fd, timeoutms)) {
+               if (ast_wait_for_output(fd, timeoutms - elapsed)) {
                        return -1;
                }
 
                        return -1;
                }
 
@@ -1130,6 +1136,14 @@ int ast_carefulwrite(int fd, char *s, int len, int timeoutms)
                len -= res;
                s += res;
                res = 0;
                len -= res;
                s += res;
                res = 0;
+
+               elapsed = ast_tvdiff_ms(ast_tvnow(), start);
+               if (elapsed >= timeoutms) {
+                       /* We've taken too long to write 
+                        * This is only an error condition if we haven't finished writing. */
+                       res = len ? -1 : 0;
+                       break;
+               }
        }
 
        return res;
        }
 
        return res;
@@ -1139,11 +1153,10 @@ int ast_careful_fwrite(FILE *f, int fd, const char *src, size_t len, int timeout
 {
        struct timeval start = ast_tvnow();
        int n = 0;
 {
        struct timeval start = ast_tvnow();
        int n = 0;
+       int elapsed = 0;
 
        while (len) {
 
        while (len) {
-               int elapsed;
-
-               if (ast_wait_for_output(fd, timeoutms)) {
+               if (ast_wait_for_output(fd, timeoutms - elapsed)) {
                        /* poll returned a fatal error, so bail out immediately. */
                        return -1;
                }
                        /* poll returned a fatal error, so bail out immediately. */
                        return -1;
                }
@@ -1168,7 +1181,7 @@ int ast_careful_fwrite(FILE *f, int fd, const char *src, size_t len, int timeout
                src += n;
 
                elapsed = ast_tvdiff_ms(ast_tvnow(), start);
                src += n;
 
                elapsed = ast_tvdiff_ms(ast_tvnow(), start);
-               if (elapsed > timeoutms) {
+               if (elapsed >= timeoutms) {
                        /* We've taken too long to write 
                         * This is only an error condition if we haven't finished writing. */
                        n = len ? -1 : 0;
                        /* We've taken too long to write 
                         * This is only an error condition if we haven't finished writing. */
                        n = len ? -1 : 0;