aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorRafael G. Martins <rafael@rafaelmartins.eng.br>2018-12-21 03:55:00 +0100
committerRafael G. Martins <rafael@rafaelmartins.eng.br>2018-12-21 03:55:00 +0100
commiteac073d479dfbe5ecf9c5fc7180f7b29da6d1298 (patch)
tree14db2b6f4c921e7c462b20d59a61fc2cf5446625 /src
parent62919eee3ef5fbad678034c21948abed523fa47e (diff)
downloadblogc-eac073d479dfbe5ecf9c5fc7180f7b29da6d1298.tar.gz
blogc-eac073d479dfbe5ecf9c5fc7180f7b29da6d1298.tar.bz2
blogc-eac073d479dfbe5ecf9c5fc7180f7b29da6d1298.zip
wip
Diffstat (limited to 'src')
-rw-r--r--src/blogc-runserver/httpd.c58
-rw-r--r--src/common/error.c3
-rw-r--r--src/common/error.h1
-rw-r--r--src/common/thread.h23
-rw-r--r--src/common/thread_pthread.c82
5 files changed, 154 insertions, 13 deletions
diff --git a/src/blogc-runserver/httpd.c b/src/blogc-runserver/httpd.c
index 6cbd198..1c27b3d 100644
--- a/src/blogc-runserver/httpd.c
+++ b/src/blogc-runserver/httpd.c
@@ -21,6 +21,7 @@
#include <pthread.h>
#include "../common/error.h"
#include "../common/file.h"
+#include "../common/thread.h"
#include "../common/utils.h"
#include "mime.h"
#include "httpd-utils.h"
@@ -28,7 +29,7 @@
#define LISTEN_BACKLOG 100
typedef struct {
- pthread_t thread;
+ bc_thread_t *thread;
bool initialized;
} thread_data_t;
@@ -212,9 +213,9 @@ point2:
point1:
fprintf(stderr, "[Thread-%zu] %s - - \"%s\" %d\n", thread_id + 1,
ip, conn_line, status_code);
- free(conn_line);
bc_strv_free(pieces);
point0:
+ free(conn_line);
free(ip);
close(client_socket);
return NULL;
@@ -257,7 +258,7 @@ int
br_httpd_run(const char *host, const char *port, const char *docroot,
size_t max_threads)
{
- int err;
+ int r;
struct addrinfo *result;
struct addrinfo hints = {
.ai_family = AF_UNSPEC,
@@ -268,12 +269,14 @@ br_httpd_run(const char *host, const char *port, const char *docroot,
.ai_addr = NULL,
.ai_next = NULL,
};
- if (0 != (err = getaddrinfo(host, port, &hints, &result))) {
+ if (0 != (r = getaddrinfo(host, port, &hints, &result))) {
fprintf(stderr, "Failed to get host:port info: %s\n",
- gai_strerror(err));
+ gai_strerror(r));
return 3;
}
+ bc_error_t *err = NULL;
+
thread_data_t threads[max_threads];
for (size_t i = 0; i < max_threads; i++)
threads[i].initialized = false;
@@ -380,19 +383,36 @@ br_httpd_run(const char *host, const char *port, const char *docroot,
arg->docroot = docroot;
if (threads[current_thread].initialized) {
- if (pthread_join(threads[current_thread].thread, NULL) != 0) {
- fprintf(stderr, "Failed to join thread\n");
- free(arg->ip);
- free(arg);
+ bc_thread_join(threads[current_thread].thread, &err);
+ bc_thread_free(threads[current_thread].thread);
+ threads[current_thread].thread = NULL;
+ threads[current_thread].initialized = false;
+ if (err != NULL) {
+ bc_error_print(err, "blogc-runserver");
+ bc_error_free(err);
+ err = NULL;
+ if (arg != NULL) {
+ free(arg->ip);
+ free(arg);
+ }
rv = 3;
goto cleanup;
}
}
- if (pthread_create(&(threads[current_thread].thread), NULL,
- handle_request, arg) != 0)
- {
- fprintf(stderr, "Failed to create thread\n");
+ threads[current_thread].thread = bc_thread_create(handle_request, arg,
+ false, &err);
+ if (err != NULL) {
+ bc_error_print(err, "blogc-runserver");
+ bc_error_free(err);
+ err = NULL;
+ if (arg != NULL) {
+ free(arg->ip);
+ free(arg);
+ }
+ bc_thread_free(threads[current_thread].thread);
+ threads[current_thread].thread = NULL;
+ threads[current_thread].initialized = false;
rv = 3;
goto cleanup;
}
@@ -404,6 +424,18 @@ br_httpd_run(const char *host, const char *port, const char *docroot,
}
cleanup:
+ for (size_t i = 0; i < max_threads; i++) {
+ if (threads[i].initialized && threads[i].thread != NULL) {
+ bc_thread_join(threads[i].thread, &err);
+ bc_thread_free(threads[i].thread);
+ if (err != NULL) {
+ bc_error_free(err);
+ err = NULL;
+ rv = 3;
+ }
+ }
+ }
+
close(server_socket);
cleanup0:
diff --git a/src/common/error.c b/src/common/error.c
index 4538c01..a3a08e7 100644
--- a/src/common/error.c
+++ b/src/common/error.c
@@ -118,6 +118,9 @@ bc_error_print(bc_error_t *err, const char *prefix)
case BC_ERROR_FILE:
fprintf(stderr, "error: file: %s\n", err->msg);
break;
+ case BC_ERROR_THREAD:
+ fprintf(stderr, "error: thread: %s\n", err->msg);
+ break;
case BLOGC_ERROR_SOURCE_PARSER:
fprintf(stderr, "error: source: %s\n", err->msg);
break;
diff --git a/src/common/error.h b/src/common/error.h
index a567c6d..2aac439 100644
--- a/src/common/error.h
+++ b/src/common/error.h
@@ -17,6 +17,7 @@ typedef enum {
// errors for src/common
BC_ERROR_CONFIG_PARSER = 1,
BC_ERROR_FILE,
+ BC_ERROR_THREAD,
// errors for src/blogc
BLOGC_ERROR_SOURCE_PARSER = 100,
diff --git a/src/common/thread.h b/src/common/thread.h
new file mode 100644
index 0000000..850d375
--- /dev/null
+++ b/src/common/thread.h
@@ -0,0 +1,23 @@
+/*
+ * blogc: A blog compiler.
+ * Copyright (C) 2014-2018 Rafael G. Martins <rafael@rafaelmartins.eng.br>
+ *
+ * This program can be distributed under the terms of the BSD License.
+ * See the file LICENSE.
+ */
+
+#ifndef _THREAD_H
+#define _THREAD_H
+
+#include <stdbool.h>
+
+typedef void* (*bc_thread_func_t) (void *arg);
+
+typedef struct _bc_thread_t bc_thread_t;
+
+bc_thread_t* bc_thread_create(bc_thread_func_t func, void *arg, bool detached,
+ bc_error_t **err);
+void bc_thread_join(bc_thread_t *thread, bc_error_t **err);
+void bc_thread_free(bc_thread_t *thread);
+
+#endif /* _THREAD_H */
diff --git a/src/common/thread_pthread.c b/src/common/thread_pthread.c
new file mode 100644
index 0000000..a85a0c7
--- /dev/null
+++ b/src/common/thread_pthread.c
@@ -0,0 +1,82 @@
+/*
+ * blogc: A blog compiler.
+ * Copyright (C) 2014-2018 Rafael G. Martins <rafael@rafaelmartins.eng.br>
+ *
+ * This program can be distributed under the terms of the BSD License.
+ * See the file LICENSE.
+ */
+
+#include <stdbool.h>
+#include <string.h>
+#include <pthread.h>
+#include <stdlib.h>
+#include "error.h"
+#include "utils.h"
+#include "thread.h"
+
+struct _bc_thread_t {
+ pthread_t thread;
+};
+
+
+bc_thread_t*
+bc_thread_create(bc_thread_func_t func, void *arg, bool detached, bc_error_t **err)
+{
+ if (err == NULL || *err != NULL)
+ return NULL;
+
+ int r;
+
+ pthread_attr_t attr;
+ pthread_attr_t *attrp = NULL;
+
+ if (detached) {
+
+ if (0 != (r = pthread_attr_init(&attr))) {
+ *err = bc_error_new_printf(BC_ERROR_THREAD,
+ "Failed to initialize thread attributes: %s", strerror(r));
+ return NULL;
+ }
+
+ if (0 != (r = pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED))) {
+ *err = bc_error_new_printf(BC_ERROR_THREAD,
+ "Failed to mark thread as detached: %s", strerror(r));
+ return NULL;
+ }
+
+ attrp = &attr;
+ }
+
+ bc_thread_t *rv = bc_malloc(sizeof(bc_thread_t));
+
+ if (0 != (r = pthread_create(&(rv->thread), attrp, func, arg))) {
+ *err = bc_error_new_printf(BC_ERROR_THREAD,
+ "Failed to create thread: %s", strerror(r));
+ free(rv);
+ return NULL;
+ }
+
+ return rv;
+}
+
+
+void
+bc_thread_join(bc_thread_t *thread, bc_error_t **err)
+{
+ if (thread == NULL || err == NULL || *err != NULL)
+ return;
+
+ int r;
+
+ if (0 != (r = pthread_join(thread->thread, NULL))) {
+ *err = bc_error_new_printf(BC_ERROR_THREAD,
+ "Failed to join thread: %s", strerror(r));
+ }
+}
+
+
+void
+bc_thread_free(bc_thread_t *thread)
+{
+ free(thread);
+}