Commit 01ae8736e96acc7ea120b0653bef21ae84e449ec
1 parent
7f688412
now a child is spawned and writes random values in a shared memory segment. Thes…
…e values will be shown in the me action
Showing
8 changed files
with
141 additions
and
21 deletions
@@ -4,9 +4,9 @@ | @@ -4,9 +4,9 @@ | ||
4 | # Project related configuration options | 4 | # Project related configuration options |
5 | #--------------------------------------------------------------------------- | 5 | #--------------------------------------------------------------------------- |
6 | DOXYFILE_ENCODING = UTF-8 | 6 | DOXYFILE_ENCODING = UTF-8 |
7 | -PROJECT_NAME = server | 7 | +PROJECT_NAME = Server |
8 | PROJECT_NUMBER = 0.0.1 | 8 | PROJECT_NUMBER = 0.0.1 |
9 | -PROJECT_BRIEF = basic server infrastructure | 9 | +PROJECT_BRIEF = "HTTP/REST server implementation" |
10 | PROJECT_LOGO = | 10 | PROJECT_LOGO = |
11 | OUTPUT_DIRECTORY = docs | 11 | OUTPUT_DIRECTORY = docs |
12 | CREATE_SUBDIRS = NO | 12 | CREATE_SUBDIRS = NO |
@@ -27,7 +27,7 @@ INHERIT_DOCS = YES | @@ -27,7 +27,7 @@ INHERIT_DOCS = YES | ||
27 | SEPARATE_MEMBER_PAGES = NO | 27 | SEPARATE_MEMBER_PAGES = NO |
28 | TAB_SIZE = 8 | 28 | TAB_SIZE = 8 |
29 | ALIASES = | 29 | ALIASES = |
30 | -OPTIMIZE_OUTPUT_FOR_C = NO | 30 | +OPTIMIZE_OUTPUT_FOR_C = YES |
31 | OPTIMIZE_OUTPUT_JAVA = NO | 31 | OPTIMIZE_OUTPUT_JAVA = NO |
32 | OPTIMIZE_FOR_FORTRAN = NO | 32 | OPTIMIZE_FOR_FORTRAN = NO |
33 | OPTIMIZE_OUTPUT_VHDL = NO | 33 | OPTIMIZE_OUTPUT_VHDL = NO |
@@ -40,7 +40,7 @@ CLASS(HttpResponse) { | @@ -40,7 +40,7 @@ CLASS(HttpResponse) { | ||
40 | 40 | ||
41 | HttpResponse httpResponse304(int, const char *); | 41 | HttpResponse httpResponse304(int, const char *); |
42 | HttpResponse httpResponse404(); | 42 | HttpResponse httpResponse404(); |
43 | -HttpResponse httpResponseMe(); | 43 | +HttpResponse httpResponseMe(int); |
44 | HttpResponse httpResponseImage(int); | 44 | HttpResponse httpResponseImage(int); |
45 | 45 | ||
46 | #endif // __HTTP_RESPONSE_H__ | 46 | #endif // __HTTP_RESPONSE_H__ |
@@ -37,12 +37,12 @@ | @@ -37,12 +37,12 @@ | ||
37 | " \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">\n" \ | 37 | " \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">\n" \ |
38 | "<html xmlns=\"http://www.w3.org/1999/xhtml\" xml:lang=\"en\" lang=\"en\">\n" \ | 38 | "<html xmlns=\"http://www.w3.org/1999/xhtml\" xml:lang=\"en\" lang=\"en\">\n" \ |
39 | "<head><title>200 - OK</title></head>" \ | 39 | "<head><title>200 - OK</title></head>" \ |
40 | - "<body><h1>200 - OK</h1><img src=\"/image/\" /></body>" \ | 40 | + "<body><h1>200 - OK</h1><img src=\"/image/\" /><hr />%02d</body>" \ |
41 | "</html>" | 41 | "</html>" |
42 | 42 | ||
43 | 43 | ||
44 | HttpResponse | 44 | HttpResponse |
45 | -httpResponseMe() | 45 | +httpResponseMe(int value) |
46 | { | 46 | { |
47 | char buffer[200]; | 47 | char buffer[200]; |
48 | HttpResponse response; | 48 | HttpResponse response; |
@@ -58,8 +58,8 @@ httpResponseMe() | @@ -58,8 +58,8 @@ httpResponseMe() | ||
58 | 58 | ||
59 | message->type = HTTP_MESSAGE_BUFFERED; | 59 | message->type = HTTP_MESSAGE_BUFFERED; |
60 | message->nbody = sizeof(RESP_DATA) - 1; | 60 | message->nbody = sizeof(RESP_DATA) - 1; |
61 | - message->body = calloc(1, sizeof(RESP_DATA)); | ||
62 | - strcpy(message->body, RESP_DATA); | 61 | + message->body = calloc(1, sizeof(RESP_DATA)-2); |
62 | + sprintf(message->body, RESP_DATA, value); | ||
63 | 63 | ||
64 | sprintf(buffer, "%d", message->nbody); | 64 | sprintf(buffer, "%d", message->nbody); |
65 | httpHeaderAdd(&(message->header), | 65 | httpHeaderAdd(&(message->header), |
@@ -20,10 +20,12 @@ ctor(void * _this, va_list * params) | @@ -20,10 +20,12 @@ ctor(void * _this, va_list * params) | ||
20 | { | 20 | { |
21 | HttpWorker this = _this; | 21 | HttpWorker this = _this; |
22 | char * id = va_arg(*params, char *); | 22 | char * id = va_arg(*params, char *); |
23 | + int * val = va_arg(*params, int *); | ||
23 | char cbuf_id[100]; | 24 | char cbuf_id[100]; |
24 | 25 | ||
25 | - this->id = malloc(strlen(id) + 1); | 26 | + this->id = malloc(strlen(id) + 1); |
26 | strcpy(this->id, id); | 27 | strcpy(this->id, id); |
28 | + this->val = val; | ||
27 | 29 | ||
28 | sprintf(cbuf_id, "%s_%s", "parser", id); | 30 | sprintf(cbuf_id, "%s_%s", "parser", id); |
29 | this->pbuf = new(Cbuf, cbuf_id, REQUEST_PARSER_BUFFER_MAX); | 31 | this->pbuf = new(Cbuf, cbuf_id, REQUEST_PARSER_BUFFER_MAX); |
@@ -58,6 +60,7 @@ _clone(void * _this, void * _base) | @@ -58,6 +60,7 @@ _clone(void * _this, void * _base) | ||
58 | HttpWorker base = _base; | 60 | HttpWorker base = _base; |
59 | 61 | ||
60 | this->id = NULL; | 62 | this->id = NULL; |
63 | + this->val = base->val; | ||
61 | this->pbuf = NULL; | 64 | this->pbuf = NULL; |
62 | this->wbuf = NULL; | 65 | this->wbuf = NULL; |
63 | 66 |
@@ -56,7 +56,7 @@ httpWorkerProcess(HttpWorker this, int fd) | @@ -56,7 +56,7 @@ httpWorkerProcess(HttpWorker this, int fd) | ||
56 | 56 | ||
57 | if (0 == strcmp("GET", request->method) && | 57 | if (0 == strcmp("GET", request->method) && |
58 | 0 == strcmp("/me/", request->uri)) { | 58 | 0 == strcmp("/me/", request->uri)) { |
59 | - response = (HttpMessage)httpResponseMe(); | 59 | + response = (HttpMessage)httpResponseMe(*(this->val)); |
60 | } | 60 | } |
61 | else if (0 == strcmp("GET", request->method) && | 61 | else if (0 == strcmp("GET", request->method) && |
62 | 0 == strcmp("/image/", request->uri)) { | 62 | 0 == strcmp("/image/", request->uri)) { |
@@ -48,6 +48,14 @@ serverRun(Server this) | @@ -48,6 +48,14 @@ serverRun(Server this) | ||
48 | * this single process. | 48 | * this single process. |
49 | * What we can first do to get some processing between read/write | 49 | * What we can first do to get some processing between read/write |
50 | * cicles is to use the poll timeout. | 50 | * cicles is to use the poll timeout. |
51 | + * A first candidate for a separate process would be the | ||
52 | + * generation of the responses piped responses then still need | ||
53 | + * to open the filehandle in this process and reading and | ||
54 | + * writing would be done here. So the benefit might not be | ||
55 | + * very big. Otherwise we could share the read and write | ||
56 | + * ringbuffer as well as the message queues. Then the child | ||
57 | + * process can do the file readings, but this would involve | ||
58 | + * some more IPC. | ||
51 | */ | 59 | */ |
52 | while (!doShutdown) //! until error or signal | 60 | while (!doShutdown) //! until error or signal |
53 | { | 61 | { |
@@ -20,12 +20,19 @@ | @@ -20,12 +20,19 @@ | ||
20 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | 20 | * along with this program. If not, see <http://www.gnu.org/licenses/>. |
21 | */ | 21 | */ |
22 | 22 | ||
23 | -#include <stdio.h> | ||
24 | -#include <socket.h> | ||
25 | -#include <string.h> | 23 | +#include <unistd.h> |
24 | +#include <stdlib.h> | ||
25 | +#include <fcntl.h> | ||
26 | 26 | ||
27 | #include <sys/time.h> | 27 | #include <sys/time.h> |
28 | #include <sys/resource.h> | 28 | #include <sys/resource.h> |
29 | +#include <sys/types.h> | ||
30 | +#include <sys/wait.h> | ||
31 | +#include <sys/time.h> | ||
32 | +#include <sys/signal.h> | ||
33 | +#include <sys/param.h> | ||
34 | +#include <sys/stat.h> | ||
35 | +#include <sys/mman.h> | ||
29 | 36 | ||
30 | #include "server.h" | 37 | #include "server.h" |
31 | #include "logger.h" | 38 | #include "logger.h" |
@@ -35,25 +42,126 @@ | @@ -35,25 +42,126 @@ | ||
35 | 42 | ||
36 | #include "utils/signalHandling.h" | 43 | #include "utils/signalHandling.h" |
37 | 44 | ||
45 | +//#define DEFAULT_SECS 0 | ||
46 | +//#define DEFAULT_USECS (1000000 / HZ) | ||
47 | +#define DEFAULT_SECS 1 | ||
48 | +#define DEFAULT_USECS 0 | ||
49 | + | ||
50 | +void nullhandler() {} | ||
51 | + | ||
38 | void daemonize(void); | 52 | void daemonize(void); |
39 | 53 | ||
40 | int | 54 | int |
41 | main() | 55 | main() |
42 | { | 56 | { |
43 | - Logger logger = new(LoggerSyslog, LOGGER_ERR); | ||
44 | - HttpWorker worker = new(HttpWorker, "my"); | ||
45 | - Server server = new(Server, logger, worker, 11212, SOMAXCONN); | 57 | + pid_t pid; |
58 | + long psize = sysconf(_SC_PAGESIZE); | ||
59 | + int status; | ||
60 | + int shm; | ||
61 | + int * value; | ||
46 | 62 | ||
47 | struct rlimit limit = {RLIM_INFINITY, RLIM_INFINITY}; | 63 | struct rlimit limit = {RLIM_INFINITY, RLIM_INFINITY}; |
48 | setrlimit(RLIMIT_CPU, &limit); | 64 | setrlimit(RLIMIT_CPU, &limit); |
49 | 65 | ||
50 | init_signals(); | 66 | init_signals(); |
51 | - //daemonize(); | ||
52 | - serverRun(server); | ||
53 | 67 | ||
54 | - delete(&server); | ||
55 | - delete(&worker); | ||
56 | - delete(&logger); | 68 | + shm = shm_open("/fooshm", O_RDWR|O_CREAT, S_IRWXU); |
69 | + ftruncate(shm, psize); | ||
70 | + | ||
71 | + switch((pid = fork())) { | ||
72 | + case -1: | ||
73 | + break; | ||
74 | + | ||
75 | + case 0: | ||
76 | + { | ||
77 | + sigset_t block_these, pause_mask; | ||
78 | + struct sigaction s; | ||
79 | + struct itimerval interval; | ||
80 | + | ||
81 | + value = mmap (0, sizeof(int), PROT_READ|PROT_WRITE, | ||
82 | + MAP_SHARED, shm, 0); | ||
83 | + *value = 0; | ||
84 | + | ||
85 | + close(shm); | ||
86 | + | ||
87 | + /* Block SIGALRM */ | ||
88 | + sigemptyset(&block_these); | ||
89 | + sigaddset(&block_these, SIGALRM); | ||
90 | + sigprocmask(SIG_BLOCK, &block_these, &pause_mask); | ||
91 | + | ||
92 | + /* Set up handler for SIGALRM */ | ||
93 | + sigemptyset(&s.sa_mask); | ||
94 | + sigaddset(&s.sa_mask, SIGINT); | ||
95 | + s.sa_flags = 0; | ||
96 | + s.sa_handler = nullhandler; | ||
97 | + if (sigaction(SIGALRM, &s, NULL) < 0) { | ||
98 | + perror("sigaction SIGALRM"); | ||
99 | + exit (1); | ||
100 | + } | ||
101 | + | ||
102 | + interval.it_value.tv_sec = DEFAULT_SECS; | ||
103 | + interval.it_value.tv_usec = DEFAULT_USECS; | ||
104 | + interval.it_interval.tv_sec = DEFAULT_SECS; | ||
105 | + interval.it_interval.tv_usec = DEFAULT_USECS; | ||
106 | + | ||
107 | + setitimer(ITIMER_REAL, &interval, NULL); | ||
108 | + | ||
109 | + // child | ||
110 | + while(!doShutdown) { | ||
111 | + *value = rand() % 10; | ||
112 | + sigsuspend(&pause_mask); | ||
113 | + } | ||
114 | + | ||
115 | + _exit(EXIT_SUCCESS); | ||
116 | + } | ||
117 | + | ||
118 | + default: | ||
119 | + { | ||
120 | + Logger logger; | ||
121 | + HttpWorker worker; | ||
122 | + Server server; | ||
123 | + | ||
124 | + value = mmap (0, sizeof(int), PROT_READ|PROT_WRITE, | ||
125 | + MAP_SHARED, shm, 0); | ||
126 | + | ||
127 | + shm_unlink("/fooshm"); | ||
128 | + close(shm); | ||
129 | + | ||
130 | + logger = new(LoggerSyslog, LOGGER_ERR); | ||
131 | + worker = new(HttpWorker, "my", value); | ||
132 | + server = new(Server, logger, worker, 11212, SOMAXCONN); | ||
133 | + | ||
134 | + //daemonize(); | ||
135 | + serverRun(server); | ||
136 | + | ||
137 | + do { | ||
138 | + pid_t w; | ||
139 | + | ||
140 | + w = waitpid(pid, &status, WUNTRACED | WCONTINUED); | ||
141 | + | ||
142 | + if (w == -1) { | ||
143 | + perror("waitpid"); | ||
144 | + exit(EXIT_FAILURE); | ||
145 | + } | ||
146 | + | ||
147 | + if (WIFEXITED(status)) { | ||
148 | + printf("exited, status=%d\n", WEXITSTATUS(status)); | ||
149 | + } else if (WIFSIGNALED(status)) { | ||
150 | + printf("killed by signal %d\n", WTERMSIG(status)); | ||
151 | + } else if (WIFSTOPPED(status)) { | ||
152 | + printf("stopped by signal %d\n", WSTOPSIG(status)); | ||
153 | + } else if (WIFCONTINUED(status)) { | ||
154 | + printf("continued\n"); | ||
155 | + } | ||
156 | + } while (!WIFEXITED(status) && !WIFSIGNALED(status)); | ||
157 | + | ||
158 | + delete(&server); | ||
159 | + delete(&worker); | ||
160 | + delete(&logger); | ||
161 | + } | ||
162 | + | ||
163 | + break; | ||
164 | + } | ||
57 | 165 | ||
58 | return 0; | 166 | return 0; |
59 | } | 167 | } |
Please
register
or
login
to post a comment