forked from lda/telodendria
Fix occasional "Bad Request" response by waiting for data to be sent.
This also makes UtilGetDelim() and UtilGetLine() thread safe in that it isn't setting a global errno. Of course, errno should be thread safe already, but this makes it much less ambiguous.
This commit is contained in:
parent
92cc2206a1
commit
a8beded518
3 changed files with 33 additions and 16 deletions
|
@ -41,6 +41,8 @@
|
|||
#include <arpa/inet.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
#include <errno.h>
|
||||
|
||||
static const char ENABLE = 1;
|
||||
|
||||
struct HttpServer
|
||||
|
@ -454,25 +456,38 @@ HttpServerWorkerThread(void *args)
|
|||
HashMap *requestParams;
|
||||
ssize_t requestPathLen;
|
||||
|
||||
int lineError = -1;
|
||||
|
||||
ssize_t i = 0;
|
||||
HttpRequestMethod requestMethod;
|
||||
|
||||
if (!fp)
|
||||
{
|
||||
/* Block for 1 millisecond before continuing so we don't
|
||||
* murder the CPU */
|
||||
* murder the CPU if the queue is empty. */
|
||||
UtilSleepMillis(1);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Get the first line of the request */
|
||||
lineLen = UtilGetLine(&line, &lineSize, fp);
|
||||
/* Get the first line of the request.
|
||||
*
|
||||
* Every once in a while, we're too fast for the client. When this
|
||||
* happens, UtilGetLine() sets lineError to EAGAIN. If we get
|
||||
* EAGAIN, then clear the error on the stream and try again
|
||||
* after 1ms. This is typically more than enough time for the
|
||||
* client to send data. */
|
||||
while ((lineLen = UtilGetLine(&line, &lineSize, fp, &lineError)) == -1
|
||||
&& lineError == EAGAIN)
|
||||
{
|
||||
clearerr(fp);
|
||||
UtilSleepMillis(1);
|
||||
}
|
||||
|
||||
if (lineLen == -1)
|
||||
{
|
||||
goto bad_request;
|
||||
}
|
||||
|
||||
|
||||
requestMethodPtr = line;
|
||||
for (i = 0; i < lineLen; i++)
|
||||
{
|
||||
|
@ -535,7 +550,7 @@ HttpServerWorkerThread(void *args)
|
|||
goto internal_error;
|
||||
}
|
||||
|
||||
while ((lineLen = UtilGetLine(&line, &lineSize, fp)) != -1)
|
||||
while ((lineLen = UtilGetLine(&line, &lineSize, fp, &lineError)) != -1)
|
||||
{
|
||||
char *headerKey;
|
||||
char *headerValue;
|
||||
|
|
20
src/Util.c
20
src/Util.c
|
@ -31,8 +31,9 @@
|
|||
#include <ctype.h>
|
||||
#include <math.h>
|
||||
#include <time.h>
|
||||
#include <sys/time.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <sys/time.h>
|
||||
#include <limits.h>
|
||||
|
||||
unsigned long
|
||||
|
@ -179,7 +180,7 @@ UtilStringToBytes(char *str)
|
|||
}
|
||||
|
||||
ssize_t
|
||||
UtilGetDelim(char **linePtr, size_t * n, int delim, FILE * stream)
|
||||
UtilGetDelim(char **linePtr, size_t * n, int delim, FILE * stream, int *err)
|
||||
{
|
||||
char *curPos, *newLinePtr;
|
||||
size_t newLinePtrLen;
|
||||
|
@ -187,7 +188,7 @@ UtilGetDelim(char **linePtr, size_t * n, int delim, FILE * stream)
|
|||
|
||||
if (!linePtr || !n || !stream)
|
||||
{
|
||||
errno = EINVAL;
|
||||
*err = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -197,7 +198,7 @@ UtilGetDelim(char **linePtr, size_t * n, int delim, FILE * stream)
|
|||
|
||||
if (!(*linePtr = Malloc(*n)))
|
||||
{
|
||||
errno = ENOMEM;
|
||||
*err = ENOMEM;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
@ -210,6 +211,7 @@ UtilGetDelim(char **linePtr, size_t * n, int delim, FILE * stream)
|
|||
|
||||
if (ferror(stream) || (c == EOF && curPos == *linePtr))
|
||||
{
|
||||
*err = errno;
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -223,9 +225,9 @@ UtilGetDelim(char **linePtr, size_t * n, int delim, FILE * stream)
|
|||
if (SSIZE_MAX / 2 < *n)
|
||||
{
|
||||
#ifdef EOVERFLOW
|
||||
errno = EOVERFLOW;
|
||||
*err = EOVERFLOW;
|
||||
#else
|
||||
errno = ERANGE;
|
||||
*err = ERANGE;
|
||||
#endif
|
||||
return -1;
|
||||
}
|
||||
|
@ -234,7 +236,7 @@ UtilGetDelim(char **linePtr, size_t * n, int delim, FILE * stream)
|
|||
|
||||
if (!(newLinePtr = Realloc(*linePtr, newLinePtrLen)))
|
||||
{
|
||||
errno = ENOMEM;
|
||||
*err = ENOMEM;
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -256,7 +258,7 @@ UtilGetDelim(char **linePtr, size_t * n, int delim, FILE * stream)
|
|||
}
|
||||
|
||||
ssize_t
|
||||
UtilGetLine(char **linePtr, size_t * n, FILE * stream)
|
||||
UtilGetLine(char **linePtr, size_t * n, FILE * stream, int *err)
|
||||
{
|
||||
return UtilGetDelim(linePtr, n, '\n', stream);
|
||||
return UtilGetDelim(linePtr, n, '\n', stream, err);
|
||||
}
|
||||
|
|
|
@ -104,9 +104,9 @@ extern size_t
|
|||
UtilStringToBytes(char *);
|
||||
|
||||
extern ssize_t
|
||||
UtilGetDelim(char **, size_t *, int, FILE *);
|
||||
UtilGetDelim(char **, size_t *, int, FILE *, int *);
|
||||
|
||||
extern ssize_t
|
||||
UtilGetLine(char **, size_t *, FILE *);
|
||||
UtilGetLine(char **, size_t *, FILE *, int *);
|
||||
|
||||
#endif /* TELODENDRIA_UTIL_H */
|
||||
|
|
Loading…
Reference in a new issue