Skip to content

Commit d314ae2

Browse files
committed
Fix some bugs
1 parent d2c9738 commit d314ae2

File tree

2 files changed

+41
-26
lines changed

2 files changed

+41
-26
lines changed

tinyhttpd/README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ use `./httpd <path> <port> &` to run. \
1111

1212
## known issues
1313
1. httpd occupy nearly 100% CPU.
14-
2. httpd will exit when more than about 10 connection in a short time.
14+
2. httpd will killed by SIGSEGV when many connection in a short time.
1515

1616
## TODO list:
1717
1. Make every thread in thread pool have a buffer. Because buffer was initialized at the beginning of many function. That will degrade perfermance largely. (DONE, use thread-specific data to solve it, every buffer will be initialized only once)

tinyhttpd/httpd.c

+40-25
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
#include <stdio.h>
66
#include <string.h>
77
#include <sys/epoll.h>
8+
#include <signal.h>
89
#include <unistd.h>
910
#include <sys/stat.h>
1011
#include <unistd.h>
@@ -30,9 +31,16 @@ char file_types[MAXFILETYPES][2][64] = {
3031
thread_pool *pool = NULL;
3132
int get_line(int fd, char *buf, int size);
3233

34+
void send_nosignal(int fd, char*buf, size_t size)
35+
{
36+
if(send(fd, buf, size, MSG_NOSIGNAL) < 0)
37+
perror("send");
38+
}
39+
3340
void *malloc_specific_data()
3441
{
3542
int *id = (int*)pthread_getspecific(buf_id);
43+
if((*id) == MAX_SPECIFIC_DATA) return NULL;
3644
++(*id);
3745
return pthread_getspecific(buf_key[(*id)-1]);
3846
}
@@ -75,7 +83,7 @@ void cat(int fd, const char *filename)
7583
fgets(buf, MAX_SPECIFIC_DATA_SIZE, resource);
7684
while(!feof(resource))
7785
{
78-
send(fd, buf, strlen(buf), 0);
86+
send_nosignal(fd, buf, strlen(buf));
7987
fgets(buf, MAX_SPECIFIC_DATA_SIZE, resource);
8088
}
8189
fclose(resource);
@@ -91,11 +99,11 @@ void cat_bytes(int fd, const char *filename)
9199
FILE *resource = fopen(filename, "rb");
92100
char *buf = malloc_specific_data();
93101
size_t n;
94-
n = fread(buf, 1, 1024, resource);
102+
n = fread(buf, 1, MAX_SPECIFIC_DATA_SIZE, resource);
95103
while(!feof(resource))
96104
{
97-
send(fd, buf, n, 0);
98-
n = fread(buf, 1, 1024, resource);
105+
send_nosignal(fd, buf, n);
106+
n = fread(buf, 1, MAX_SPECIFIC_DATA_SIZE, resource);
99107
}
100108
fclose(resource);
101109
}
@@ -104,13 +112,13 @@ const char* get_filetype(char *buf, const char *filename)
104112
{
105113
char *tmp = malloc_specific_data();
106114
int i = 0;
107-
while(filename[i]!='\0'&&filename[i]!='.') ++i;
115+
while(filename[i]!='\0'&&filename[i]!='.'&&i<MAX_SPECIFIC_DATA_SIZE-2) ++i;
108116
if(filename[i] == '\0') strcpy(buf, "text/html");
109117
else
110118
{
111119
int j = 0;
112120
++i;
113-
while(filename[i]!='\0')
121+
while(filename[i]!='\0'&&i<MAX_SPECIFIC_DATA_SIZE-1)
114122
tmp[j++]=filename[i++];
115123
tmp[j]='\0';
116124
for(i=0; i<MAXFILETYPES; ++i)
@@ -128,15 +136,15 @@ void unimplemented(int fd)
128136
char *buf = malloc_specific_data();
129137
discard_headers(fd, buf);
130138
sprintf(buf, "HTTP/1.0 501 Method Not Implemented\r\n");
131-
send(fd, buf, strlen(buf), 0);
139+
send_nosignal(fd, buf, strlen(buf));
132140
sprintf(buf, SERV_STRING);
133-
send(fd, buf, strlen(buf), 0);
141+
send_nosignal(fd, buf, strlen(buf));
134142
sprintf(buf, "Content-Type: text/html\r\n");
135-
send(fd, buf, strlen(buf), 0);
143+
send_nosignal(fd, buf, strlen(buf));
136144
sprintf(buf, "Connection: closed\r\n");
137-
send(fd, buf, strlen(buf), 0);
145+
send_nosignal(fd, buf, strlen(buf));
138146
sprintf(buf, "\r\n");
139-
send(fd, buf, strlen(buf), 0);
147+
send_nosignal(fd, buf, strlen(buf));
140148
char *filename = malloc_specific_data();
141149
sprintf(filename, "%s/501.html",PATH);
142150
cat(fd, filename);
@@ -147,15 +155,15 @@ void not_found(int fd)
147155
char *buf = malloc_specific_data();
148156
discard_headers(fd, buf);
149157
sprintf(buf, "HTTP/1.0 404 NOTFOUND\r\n");
150-
send(fd, buf, strlen(buf), 0);
158+
send_nosignal(fd, buf, strlen(buf));
151159
sprintf(buf, SERV_STRING);
152-
send(fd, buf, strlen(buf), 0);
160+
send_nosignal(fd, buf, strlen(buf));
153161
sprintf(buf, "Content-Type: text/html\r\n");
154-
send(fd, buf, strlen(buf), 0);
162+
send_nosignal(fd, buf, strlen(buf));
155163
sprintf(buf, "Connection: closed\r\n");
156-
send(fd, buf, strlen(buf), 0);
164+
send_nosignal(fd, buf, strlen(buf));
157165
sprintf(buf, "\r\n");
158-
send(fd, buf, strlen(buf), 0);
166+
send_nosignal(fd, buf, strlen(buf));
159167
char *filename = malloc_specific_data();
160168
sprintf(filename, "%s/404.html",PATH);
161169
cat(fd, filename);
@@ -167,15 +175,15 @@ void respond_ok(int fd, const char *filename)
167175
discard_headers(fd, buf);
168176
char *ft = malloc_specific_data();
169177
sprintf(buf, "HTTP/1.0 200 OK\r\n");
170-
send(fd, buf, strlen(buf), 0);
178+
send_nosignal(fd, buf, strlen(buf));
171179
sprintf(buf, SERV_STRING);
172-
send(fd, buf, strlen(buf), 0);
180+
send_nosignal(fd, buf, strlen(buf));
173181
sprintf(buf, "Content-Type: %s\r\n", get_filetype(ft, filename));
174-
send(fd, buf, strlen(buf), 0);
182+
send_nosignal(fd, buf, strlen(buf));
175183
sprintf(buf, "Connection: closed\r\n");
176-
send(fd, buf, strlen(buf), 0);
184+
send_nosignal(fd, buf, strlen(buf));
177185
sprintf(buf, "\r\n");
178-
send(fd, buf, strlen(buf), 0);
186+
send_nosignal(fd, buf, strlen(buf));
179187
//cat(fd, filename);
180188
if(strcmp(ft, "image/jpeg") == 0)
181189
cat_bytes(fd, filename);
@@ -185,7 +193,6 @@ void respond_ok(int fd, const char *filename)
185193

186194
void *accept_request(void *arg)
187195
{
188-
printf("start accept request\n");
189196
pthread_once(&buf_once, buf_init_once);
190197
/* init thread-specific data */
191198
for(int i=0; i<MAX_SPECIFIC_DATA; ++i)
@@ -256,6 +263,10 @@ void *accept_request(void *arg)
256263
respond_ok(clifd, path);
257264
}
258265
printf("connection terminated\n");
266+
{
267+
int *k = pthread_getspecific(buf_id);
268+
*k=0;
269+
}
259270
close(clifd);
260271
return NULL;
261272
}
@@ -289,13 +300,20 @@ int get_line(int fd, char *buf, int size)
289300
buf[i] = '\0';
290301
return i;
291302
}
303+
292304
int main(int argc, char **argv)
293305
{
294306
if(argc != 3)
295307
{
296308
fprintf(stderr, "usage: %s <directory> <port>", argv[0]);
297309
exit(0);
298310
}
311+
sigset_t signal_mask;
312+
sigemptyset(&signal_mask);
313+
sigaddset(&signal_mask, SIGPIPE);
314+
if(pthread_sigmask(SIG_BLOCK, &signal_mask, NULL) == -1)
315+
perror("SIGPIPE");
316+
299317
strcpy(PATH, argv[1]);
300318
int pathlen = strlen(PATH);
301319
if(PATH[pathlen-1] == '/')
@@ -363,11 +381,8 @@ int main(int argc, char **argv)
363381
}
364382
else if(events[i].events & EPOLLIN)
365383
{
366-
printf("EPOLLIN accepted\n");
367384
int clifd = events[i].data.fd;
368-
printf("before add task\n");
369385
pool_add_task(pool, accept_request, (void*)&clifd);
370-
printf("after add task");
371386
epoll_ctl(epfd, EPOLL_CTL_DEL, clifd, NULL);
372387
}
373388
}

0 commit comments

Comments
 (0)