forked from Telodendria/Telodendria
Fix memory and connection closing errors.
This commit is contained in:
parent
6c016b813c
commit
efbbf42a6e
5 changed files with 63 additions and 38 deletions
58
src/Db.c
58
src/Db.c
|
@ -48,42 +48,42 @@ struct DbRef
|
||||||
};
|
};
|
||||||
|
|
||||||
static ssize_t
|
static ssize_t
|
||||||
DbComputeSize(HashMap *json)
|
DbComputeSize(HashMap * json)
|
||||||
{
|
{
|
||||||
char *key;
|
char *key;
|
||||||
JsonValue *val;
|
JsonValue *val;
|
||||||
MemoryInfo *a;
|
MemoryInfo *a;
|
||||||
size_t total;
|
size_t total;
|
||||||
|
|
||||||
if (!json)
|
if (!json)
|
||||||
{
|
{
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
total = 0;
|
total = 0;
|
||||||
|
|
||||||
a = MemoryInfoGet(json);
|
a = MemoryInfoGet(json);
|
||||||
if (a)
|
if (a)
|
||||||
{
|
{
|
||||||
total += MemoryInfoGetSize(a);
|
total += MemoryInfoGetSize(a);
|
||||||
}
|
}
|
||||||
|
|
||||||
while (HashMapIterate(json, &key, (void **) &val))
|
while (HashMapIterate(json, &key, (void **) &val))
|
||||||
{
|
{
|
||||||
a = MemoryInfoGet(key);
|
a = MemoryInfoGet(key);
|
||||||
if (a)
|
if (a)
|
||||||
{
|
{
|
||||||
total += MemoryInfoGetSize(a);
|
total += MemoryInfoGetSize(a);
|
||||||
}
|
}
|
||||||
|
|
||||||
a = MemoryInfoGet(val);
|
a = MemoryInfoGet(val);
|
||||||
if (a)
|
if (a)
|
||||||
{
|
{
|
||||||
total += MemoryInfoGetSize(a);
|
total += MemoryInfoGetSize(a);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return total;
|
return total;
|
||||||
}
|
}
|
||||||
|
|
||||||
Db *
|
Db *
|
||||||
|
|
|
@ -86,7 +86,7 @@ HashMapGrow(HashMap * map)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
memset(&newEntries, 0, map->capacity * sizeof(HashMapBucket *));
|
memset(newEntries, 0, map->capacity * sizeof(HashMapBucket *));
|
||||||
|
|
||||||
for (i = 0; i < oldCapacity; i++)
|
for (i = 0; i < oldCapacity; i++)
|
||||||
{
|
{
|
||||||
|
|
|
@ -77,6 +77,13 @@ struct HttpServerContext
|
||||||
FILE *stream;
|
FILE *stream;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
typedef struct HttpServerWorkerThreadArgs
|
||||||
|
{
|
||||||
|
HttpServer *server;
|
||||||
|
int id;
|
||||||
|
pthread_t thread;
|
||||||
|
} HttpServerWorkerThreadArgs;
|
||||||
|
|
||||||
static HttpServerContext *
|
static HttpServerContext *
|
||||||
HttpServerContextCreate(HttpRequestMethod requestMethod,
|
HttpServerContextCreate(HttpRequestMethod requestMethod,
|
||||||
char *requestPath, HashMap * requestParams, FILE * stream)
|
char *requestPath, HashMap * requestParams, FILE * stream)
|
||||||
|
@ -437,11 +444,12 @@ HttpServerFree(HttpServer * server)
|
||||||
static void *
|
static void *
|
||||||
HttpServerWorkerThread(void *args)
|
HttpServerWorkerThread(void *args)
|
||||||
{
|
{
|
||||||
HttpServer *server = (HttpServer *) args;
|
HttpServerWorkerThreadArgs *wArgs = (HttpServerWorkerThreadArgs *) args;
|
||||||
|
HttpServer *server = wArgs->server;
|
||||||
|
|
||||||
while (!server->stop)
|
while (!server->stop)
|
||||||
{
|
{
|
||||||
FILE *fp = DequeueConnection(server);
|
FILE *fp;
|
||||||
HttpServerContext *context;
|
HttpServerContext *context;
|
||||||
|
|
||||||
char *line = NULL;
|
char *line = NULL;
|
||||||
|
@ -461,6 +469,10 @@ HttpServerWorkerThread(void *args)
|
||||||
ssize_t i = 0;
|
ssize_t i = 0;
|
||||||
HttpRequestMethod requestMethod;
|
HttpRequestMethod requestMethod;
|
||||||
|
|
||||||
|
long firstRead;
|
||||||
|
|
||||||
|
fp = DequeueConnection(server);
|
||||||
|
|
||||||
if (!fp)
|
if (!fp)
|
||||||
{
|
{
|
||||||
/* Block for 1 millisecond before continuing so we don't
|
/* Block for 1 millisecond before continuing so we don't
|
||||||
|
@ -476,11 +488,20 @@ HttpServerWorkerThread(void *args)
|
||||||
* EAGAIN, then clear the error on the stream and try again
|
* EAGAIN, then clear the error on the stream and try again
|
||||||
* after 1ms. This is typically more than enough time for the
|
* after 1ms. This is typically more than enough time for the
|
||||||
* client to send data. */
|
* client to send data. */
|
||||||
|
firstRead = UtilServerTs();
|
||||||
while ((lineLen = UtilGetLine(&line, &lineSize, fp, &lineError)) == -1
|
while ((lineLen = UtilGetLine(&line, &lineSize, fp, &lineError)) == -1
|
||||||
&& lineError == EAGAIN)
|
&& lineError == EAGAIN)
|
||||||
{
|
{
|
||||||
clearerr(fp);
|
clearerr(fp);
|
||||||
UtilSleepMillis(1);
|
|
||||||
|
/* If the server is stopped, or it's been a while, just
|
||||||
|
* give up. */
|
||||||
|
if (server->stop || (UtilServerTs() - firstRead) > 1000 * 30)
|
||||||
|
{
|
||||||
|
goto finish;
|
||||||
|
}
|
||||||
|
|
||||||
|
UtilSleepMillis(5);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (lineLen == -1)
|
if (lineLen == -1)
|
||||||
|
@ -652,7 +673,7 @@ HttpServerEventThread(void *args)
|
||||||
|
|
||||||
for (i = 0; i < server->nThreads; i++)
|
for (i = 0; i < server->nThreads; i++)
|
||||||
{
|
{
|
||||||
pthread_t *workerThread = Malloc(sizeof(pthread_t));
|
HttpServerWorkerThreadArgs *workerThread = Malloc(sizeof(HttpServerWorkerThreadArgs));
|
||||||
|
|
||||||
if (!workerThread)
|
if (!workerThread)
|
||||||
{
|
{
|
||||||
|
@ -661,7 +682,10 @@ HttpServerEventThread(void *args)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pthread_create(workerThread, NULL, HttpServerWorkerThread, server) != 0)
|
workerThread->server = server;
|
||||||
|
workerThread->id = i;
|
||||||
|
|
||||||
|
if (pthread_create(&workerThread->thread, NULL, HttpServerWorkerThread, workerThread) != 0)
|
||||||
{
|
{
|
||||||
/* TODO: Make the event thread return an error to the main
|
/* TODO: Make the event thread return an error to the main
|
||||||
* thread */
|
* thread */
|
||||||
|
@ -698,9 +722,9 @@ HttpServerEventThread(void *args)
|
||||||
|
|
||||||
for (i = 0; i < server->nThreads; i++)
|
for (i = 0; i < server->nThreads; i++)
|
||||||
{
|
{
|
||||||
pthread_t *workerThread = ArrayGet(server->threadPool, i);
|
HttpServerWorkerThreadArgs *workerThread = ArrayGet(server->threadPool, i);
|
||||||
|
|
||||||
pthread_join(*workerThread, NULL);
|
pthread_join(workerThread->thread, NULL);
|
||||||
Free(workerThread);
|
Free(workerThread);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -77,6 +77,8 @@ MatrixHttpHandler(HttpServerContext * context, void *argp)
|
||||||
HttpResponseHeader(context, "Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS");
|
HttpResponseHeader(context, "Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS");
|
||||||
HttpResponseHeader(context, "Access-Control-Allow-Headers", "X-Requested-With, Content-Type, Authorization");
|
HttpResponseHeader(context, "Access-Control-Allow-Headers", "X-Requested-With, Content-Type, Authorization");
|
||||||
|
|
||||||
|
HttpResponseHeader(context, "Connection", "close");
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Web Browser Clients: Servers MUST expect that clients will approach them
|
* Web Browser Clients: Servers MUST expect that clients will approach them
|
||||||
* with OPTIONS requests... the server MUST NOT perform any logic defined
|
* with OPTIONS requests... the server MUST NOT perform any logic defined
|
||||||
|
|
|
@ -98,7 +98,6 @@ TelodendriaConfigParse(HashMap * config, LogConfig * lc)
|
||||||
|
|
||||||
if (!directive)
|
if (!directive)
|
||||||
{
|
{
|
||||||
Log(lc, LOG_WARNING, "No 'listen' directive specified; using default value, which may change.");
|
|
||||||
tConfig->listenPort = 8008;
|
tConfig->listenPort = 8008;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
Loading…
Reference in a new issue