List Info

Thread: ref to ticket 479 : CherryPy crashes on using seteuid / setegid




ref to ticket 479 : CherryPy crashes on using seteuid / setegid
user name
2006-04-04 07:31:20
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-usersgooglegroups.com
To unsubscribe from this group, send email to
cherrypy-users-unsubscribegooglegroups.com
For more options, visit this group at http://
groups.google.com/group/cherrypy-users
-~----------~----~----~----~------~----~------~--~---

[1]

about | contact  Other archives ( Real Estate discussion Medical topics )