With reference to: Ticket #479 CherryPy crashes on using
seteuid /
setegid
the "start" method in class
CherryPyWSGIServer(object)
"site-packages/cherrypy/_cpwsgiserver.py " file
sets the timeout using the socket.socket.settimeout()
method .
------------------------------------------------------------
---------------------------------
class CherryPyWSGIServer(object):
.....
def start(self):
'''
run the server forever
'''
# We don't have to trap KeyboardInterrupt or
SystemExit here,
# because cherrpy.server already does so, calling
self.stop()
for us.
# If you're using this server with another
framework, you
should
# trap those exceptions in whatever code block calls
start().
self.socket = socket.socket(socket.AF_INET,
socket.SOCK_STREAM,
socket.IPPROTO_TCP)
self.socket.setsockopt(socket.SOL_SOCKET,
socket.SO_REUSEADDR,
1)
self.socket.bind(self.bind_addr)
# Timeout so KeyboardInterrupt can be caught on
Win32
self.socket.settimeout(1)
------------------------------------------------------------
------------------------------------
Now Stepping thru the settimeout implementation in
"Python-2.4.3/Modules/socketmodule.c"
static PyObject *
1470 sock_settimeout(PySocketSockObject *s, PyObject
*arg)
1471 {
1472 double timeout;
1473
1474 if (arg == Py_None)
1475 timeout = -1.0;
1476 else {
1477 timeout = PyFloat_AsDouble(arg);
1478 if (timeout < 0.0) {
1479 if (!PyErr_Occurred())
1480
PyErr_SetString(PyExc_ValueError,
1481
"Timeout value
out of range");
1482 return NULL;
1483 }
1484 }
1485
1486 s->sock_timeout = timeout;
1487 internal_setblocking(s, timeout < 0.0);
1488
1489 Py_INCREF(Py_None);
1490 return Py_None;
1491 }
1492
lineno "1487" fisrt sets the "socket
fd" to nonblocking(
setblocking(false) ).
and now proceeding to the "socket.accept()"
implementation in
"Python-2.4.3/Modules/socketmodule.c"
1362 sock_accept(PySocketSockObject *s)
1363 {
1364 sock_addr_t addrbuf;
1365 SOCKET_T newfd;
1366 socklen_t addrlen;
1367 PyObject *sock = NULL;
1368 PyObject *addr = NULL;
1369 PyObject *res = NULL;
1370 int timeout;
1371
1372 if (!getsockaddrlen(s, &addrlen))
1373 return NULL;
1374 memset(&addrbuf, 0, addrlen);
1375
1376 #ifdef MS_WINDOWS
1377 newfd = INVALID_SOCKET;
1378 #else
1379 newfd = -1;
1380 #endif
1381
1382 if (!IS_SELECTABLE(s))
1383 return select_error();
1384
1385 Py_BEGIN_ALLOW_THREADS
1386 timeout = internal_select(s, 0);
1387 if (!timeout)
1388 newfd = accept(s->sock_fd,
(struct sockaddr *)
&addrbuf,
1389 &addrlen);
1390 Py_END_ALLOW_THREADS
1391
1392 if (timeout) {
1393 PyErr_SetString(socket_timeout,
"timed out");
1394 return NULL;
1395 }
1396
1397 #ifdef MS_WINDOWS
1398 if (newfd == INVALID_SOCKET)
1399 #else
1400 if (newfd < 0)
1401 #endif
1402 return s->errorhandler();
1403
line no "1386" calls internal_select(s, 0) ;
internal_select from
"Python-2.4.3/Modules/socketmodule.c"
649 internal_select(PySocketSockObject *s, int writing)
650 {
651 fd_set fds;
652 struct timeval tv;
653 int n;
654
655 /* Nothing to do unless we're in timeout
mode (not
non-blocking) */
656 if (s->sock_timeout <= 0.0)
657 return 0;
658
659 /* Guard against closed socket */
660 if (s->sock_fd < 0)
661 return 0;
662
663 /* Construct the arguments to select */
664 tv.tv_sec = (int)s->sock_timeout;
665 tv.tv_usec = (int)((s->sock_timeout -
tv.tv_sec) *
1e6);
666 FD_ZERO(&fds);
667 FD_SET(s->sock_fd, &fds);
668
669 /* See if the socket is ready */
670 if (writing)
671 n = select(s->sock_fd+1, NULL,
&fds, NULL,
&tv);
672 else
673 n = select(s->sock_fd+1,
&fds, NULL, NULL,
&tv);
674 if (n == 0)
675 return 1;
676 return 0;
677 }
On "2.6.11-1.1369_FC4" kernel
"select()" seems to be interrupted (
EINTR : Interrupted system call)
when two threads are running when one is doing the
select() and other
doing the "seteuid()"
below is the threaded "C" code in . so our
above fuctions returns
with "0" and in sock_accept()
line:1388 newfd = accept(s->sock_fd, (struct sockaddr
*)
&addrbuf,&addrlen);
must be returning "EAGAIN -> Resource temporarily
unavailable" since
we have gone into non-blocking and sockfd is
not readable.
//Start of code
#include <pthread.h>
#include <string.h>
#include <stdio.h>
#include <sys/select.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/fsuid.h>
#include <sys/time.h>
#include <errno.h>
extern int errno ;
void * accept_t (void*arg) ;
void * change_id_t (void*arg);
int bind_new_sock(uint16_t port) ;
void do_accept ( int sock ) ;
#define ACCEPT_T 0
#define CHANGE_ID_T 1
/* main thread */
int main(int argc , char *argv)
{
pthread_t threads [2] ;
int data1[2];
int data2[2];
int code ;
int *status;
/*create the thread */
uint16_t port = 9000 ;
data1[0] = ACCEPT_T ;
data1[1] = bind_new_sock(port) ;
if (
code=pthread_create(&threads[ACCEPT_T],NULL,accept_t,&am
p;data1) ) {
fprintf(stderr," %s\n",strerror(code) ) ;
exit(1);
}
data2[0] = CHANGE_ID_T ;
data2[0] = CHANGE_ID_T ;
data2[1] = 501 ;
if (
code=pthread_create(&threads[CHANGE_ID_T],NULL,change_id
_t,&data2) ) {
fprintf(stderr,"%s\n", strerror(code) ) ;
exit(1);
}
for(;;)
sleep(2);
}
/* accept thread */
void * accept_t (void*arg)
{
int *data = (int *) arg ;
int tid = data[0] ;
int sock = data[1] ;
for(;;) {
printf ("accept_t : accepting connections
\n" ) ;
do_accept( sock ) ;
}
return arg ;
}
void * change_id_t (void*arg)
{
int *data = (int *)arg ;
int tid = data[0] ;
uid_t seuid = data[1] ;
for(;;) {
printf ("change_id_t : changing id\n" ) ;
if ( seteuid(seuid) != 0 )
perror("seteuid()") ;
sleep(2);
if ( seteuid(0) != 0 )
perror("seteuid()") ;
}
return arg ;
}
int bind_new_sock(uint16_t port)
{
int sock;
struct sockaddr_in name;
int oflags;
struct timeval timeout ;
sock = socket (PF_INET, SOCK_STREAM, 0);
if (sock < 0)
{
perror ("socket");
exit (EXIT_FAILURE);
}
oflags = fcntl (sock, F_GETFL, 0);
if ( fcntl (sock, F_SETFL, oflags |= O_NONBLOCK) == -1 )
perror("fcntl()") ;
name.sin_family = AF_INET;
name.sin_port = htons (port);
name.sin_addr.s_addr = htonl (INADDR_ANY);
if (bind (sock, (struct sockaddr *) &name, sizeof
(name)) < 0)
{
perror ("bind");
exit (EXIT_FAILURE);
}
if (listen (sock, 1) < 0)
{
perror ("listen");
exit (EXIT_FAILURE);
}
return sock ;
}
void
do_accept (int sock)
{
struct sockaddr_in newclient;
size_t size;
int new;
fd_set rfds;
struct timeval tv;
int retval;
size = sizeof (newclient);
FD_ZERO(&rfds);
FD_SET(sock, &rfds);
/* timeout */
tv.tv_sec = 15;
tv.tv_usec = 0;
SELECT:
retval = select(sock+1, &rfds, NULL, NULL, &tv);
if (retval == -1) {
perror("select()");
//if ( errno == EINTR ){
//goto SELECT ;
//}
new = accept (sock, (struct sockaddr *) &newclient,
&size);
if (new < 0)
{
perror ("accept");
}
}
}
//End Of code
--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the
Google Groups "cherrypy-users" group.
To post to this group, send email to cherrypy-users googlegroups.com
To unsubscribe from this group, send email to
cherrypy-users-unsubscribe googlegroups.com
For more options, visit this group at http://
groups.google.com/group/cherrypy-users
-~----------~----~----~----~------~----~------~--~---
|