Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Loading…

Fix a varios bugs in fapws3 #19

Closed
wants to merge 7 commits into from

2 participants

Alexander Shigin William
Alexander Shigin
  • memleak in py_rfc1123_date;
  • segfault if handler return type isn't list, file or iterator;
  • proper handling the closing of a socket by client;
  • add example of DoS client.
William
Owner

Thanks shigin for your cooperation.

Except the "do not segfault on wrong type", I'll merge your changes. Indeed, this one has also been corrected on my local repository (with a bit more changes).

I have to see how I can merge all your changes except that one ;-(.

William

William
Owner

merged in master.

Thanks for your contribution

This issue was closed.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Commits on Dec 6, 2010
  1. Alexander Shigin

    turn off executable bit

    shigin authored
  2. Alexander Shigin

    avoid warning

    shigin authored
  3. Alexander Shigin

    fix memleak in rfc1123 date

    shigin authored
  4. Alexander Shigin

    add test

    shigin authored
  5. Alexander Shigin
  6. Alexander Shigin

    do not segfault on wrong type

    shigin authored
  7. Alexander Shigin

    add slow client

    shigin authored
This page is out of date. Refresh to see the latest.
0  INSTALL 100755 → 100644
View
File mode changed
0  README.markdown 100755 → 100644
View
File mode changed
9 fapws/_evwsgi.c
View
@@ -399,11 +399,14 @@ PyObject *py_defer_queue_size(PyObject *self, PyObject *args)
PyObject *py_rfc1123_date(PyObject *self, PyObject *args)
{
time_t t;
+ PyObject *result;
+ char *rfc_string = NULL;
if (!PyArg_ParseTuple(args, "L", &t))
return NULL;
- char *res=NULL;
- res=time_rfc1123(t);
- return PyString_FromString(res);
+ rfc_string = time_rfc1123(t);
+ result = PyString_FromString(rfc_string);
+ free(rfc_string);
+ return result;
}
2  fapws/extra.h
View
@@ -11,5 +11,5 @@ char *cur_time(char * fmt);
char *time_rfc1123(time_t t);
-char *cur_time_rfc1123();
+char *cur_time_rfc1123(void);
20 fapws/mainloop.c
View
@@ -397,6 +397,10 @@ Procedure that will write "len" bytes of "response" to the client.
*/
int write_cli(struct client *cli, char *response, size_t len, int revents)
{
+ /* XXX The design of the function is broken badly: after the first EAGAIN
+ error we should exit and wait for an EV_WRITE event. You can think about
+ slow client or some client which holds a socket but don't read from one.
+ */
size_t r=0, sent_len=MAX_BUFF;
int c=0;
if (revents & EV_WRITE){
@@ -414,13 +418,18 @@ int write_cli(struct client *cli, char *response, size_t len, int revents)
printf("host=%s,port=%i write_cli:uri=%s,r=%i,len=%i,c=%i\n", cli->remote_addr, cli->remote_port, cli->uri, (int)r, (int)len,c);
if (((int)r<0) & (errno != EAGAIN))
{
+ if (errno == EPIPE || errno == ECONNRESET) {
+ // The client closes the socket. We can log the error.
+ return 0;
+ }
cli->retry++;
fprintf(stderr,"Failed to write to the client:%s:%i, #:%i.\n", cli->remote_addr, cli->remote_port, cli->retry);
if (cli->retry>MAX_RETRY)
{
fprintf(stderr, "Connection closed after %i retries\n", cli->retry);
return 0; //stop the watcher and close the connection
- }
+ }
+ // XXX We shouldn't sleep in an event-base server.
usleep(100000); //failed but we don't want to close the watcher
}
if ((int)r==0)
@@ -432,9 +441,9 @@ int write_cli(struct client *cli, char *response, size_t len, int revents)
response+=(int)r;
len -=r ;
}
- }
- //p==len
- return 1;
+ }
+ //p==len
+ return 1;
}
else {
printf("write callback not ended correctly\n");
@@ -554,8 +563,9 @@ void write_cb(struct ev_loop *loop, struct ev_io *w, int revents)
}
//free(buff);
}
- else if (PyIter_Check(cli->response_content_obj)) //we treat Iterator object
+ else if (cli->response_content_obj != NULL && PyIter_Check(cli->response_content_obj))
{
+ //we treat Iterator object
cli->response_iter_sent++;
PyObject *pyelem = cli->response_content;
if (pyelem == NULL)
67 sample/test/slow_client.py
View
@@ -0,0 +1,67 @@
+"""The sample slow + fast client.
+
+The client can work fine if server is localhost. Otherwise time_request
+client usually takes the same time as long_request.
+"""
+
+import sys
+import socket
+import time
+import threading
+
+if len(sys.argv) > 2:
+ print "usage: %s [host[:port]]" % sys.argv[0]
+ sys.exit(1)
+
+hostname = 'localhost'
+port = 8080
+if len(sys.argv) == 2:
+ if ':' in sys.argv[1]:
+ hostname, port = sys.argv[1].split(':')
+ port = int(port)
+ else:
+ hostname = sys.argv[1]
+headers = '\r\nHost: %s\r\n\r\n' % hostname
+
+def timed(func):
+ def wrapper(*args, **kwargs):
+ start = time.time()
+ try:
+ return func(*args, **kwargs)
+ finally:
+ print '%s took %.2f sec' % (repr(func), time.time() - start)
+ return wrapper
+
+lock = threading.Lock()
+@timed
+def long_request():
+ s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+ s.connect((hostname, port))
+ s.send('GET /file HTTP/1.0' + headers)
+ for i in range(1):
+ s.recv(80)
+ time.sleep(1)
+ lock.release()
+ print 'release'
+ for i in range(10):
+ s.recv(80)
+ time.sleep(1)
+ s.close()
+
+@timed
+def time_request():
+ lock.acquire()
+ print 'acquire'
+ s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+ s.connect((hostname, port))
+ s.send('GET /time HTTP/1.0' + headers)
+ s.recv(900)
+ s.close()
+
+lock.acquire()
+fl = threading.Thread(target=long_request)
+tl = threading.Thread(target=time_request)
+fl.start()
+tl.start()
+tl.join()
+fl.join()
35 sample/test/test.py
View
@@ -0,0 +1,35 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+from time import time
+import fapws._evwsgi as evwsgi
+from fapws import base
+
+def start():
+ evwsgi.start("0.0.0.0", "8080")
+ evwsgi.set_base_module(base)
+
+ def return_file(environ, start_response):
+ start_response('200 OK', [('Content-Type','text/html')])
+ return open('big-file')
+
+ def return_tuple(environ, start_response):
+ start_response('200 OK', [('Content-Type','text/plain')])
+ return ('Hello,', " it's me ", 'Bob!')
+
+ def return_rfc_time(environ, start_response):
+ start_response('200 OK', [('Content-Type','text/plain')])
+ return [evwsgi.rfc1123_date(time())]
+
+ evwsgi.wsgi_cb(("/file", return_file))
+ evwsgi.wsgi_cb(("/tuple", return_tuple))
+ evwsgi.wsgi_cb(("/time", return_rfc_time))
+
+ evwsgi.run()
+
+if __name__=="__main__":
+ try:
+ open('big-file')
+ except IOError:
+ open('big-file', 'w').write('\n'.join('x'*1024 for i in range(1024)))
+ start()
Something went wrong with that request. Please try again.