SocketMan.py :  » Web-Server » SkunkWEB » skunkweb-3.4.4 » pylibs » SocketMan » Python Open Source

Home
Python Open Source
1.3.1.2 Python
2.Ajax
3.Aspect Oriented
4.Blog
5.Build
6.Business Application
7.Chart Report
8.Content Management Systems
9.Cryptographic
10.Database
11.Development
12.Editor
13.Email
14.ERP
15.Game 2D 3D
16.GIS
17.GUI
18.IDE
19.Installer
20.IRC
21.Issue Tracker
22.Language Interface
23.Log
24.Math
25.Media Sound Audio
26.Mobile
27.Network
28.Parser
29.PDF
30.Project Management
31.RSS
32.Search
33.Security
34.Template Engines
35.Test
36.UML
37.USB Serial
38.Web Frameworks
39.Web Server
40.Web Services
41.Web Unit
42.Wiki
43.Windows
44.XML
Python Open Source » Web Server » SkunkWEB 
SkunkWEB » skunkweb 3.4.4 » pylibs » SocketMan » SocketMan.py
#  
#  Copyright (C) 2001 Andrew T. Csillag <drew_csillag@geocities.com>
#  
#      You may distribute under the terms of either the GNU General
#      Public License or the SkunkWeb License, as specified in the
#      README file.
#   
import ProcessMgr.ProcessMgr
import fcntl
import select
import socket
import errno
if hasattr(fcntl, 'F_SETFD'): # to avoid deprecation warning with 2.2
    FCNTL = fcntl
else:
    import FCNTL
import sys
import cStringIO
import traceback
import os
import stat
import time

class SocketMan(ProcessMgr.ProcessMgr.ProcessMgr):
    def __init__(self, maxRequests=None, *args, **kw):
        self.maxRequests = maxRequests
        self.socketMap = {}
        ProcessMgr.ProcessMgr.ProcessMgr.__init__(self, *args, **kw)

    def preHandle(self):
        pass

    def postHandle(self):
        pass
    
    def _run(self):
        connectionCount = 0
        while 1:
            connectionCount += 1
            if self.maxRequests and connectionCount > self.maxRequests:
                self.logInterface.LOG('hit maxRequests, recycling')
                break
            have_connection = 0
            while not have_connection:
                try:
                    r,w,e = select.select(self.socketMap.keys(), [], [])
                except:
                    #this should only happen if errno is EINTR, but
                    #exiting is still probably the best idea here
                    v = sys.exc_info()[1]
                    if hasattr(v, 'errno') and v.errno != errno.EINTR:
                        self.logInterface.LOG("error on select: %s %s" % (
                            sys.exc_type, sys.exc_value))
                    else:
                        self.logInterface.LOG('select failed! %s:%s' %
                                              sys.exc_info()[:2])
                        self.logInterface.LOG('socketmap is %s' % (
                            self.socketMap.keys()))
                        
                    break

                s = r[0]
                try:
                    sock, addr = s.accept()
                    sock.setblocking(1)
                except socket.error, (err, errstr):
                    if err not in [errno.EAGAIN, errno.EWOULDBLOCK]:
                        raise
                else:
                    have_connection = 1

            if not have_connection: #because of a select error
                self.logInterface.LOG('SM exiting due to no connection')
                break # die!
            
            r = None
            try:
                #self.logInterface.LOG('calling %s for %s' % (
                #    self.socketMap[s], sock))
                try:
                    self.preHandle()
                except:
                    self.logInterface.ERROR('preHandle died %s %s %s' %
                                            sys.exc_info())
                    
                r = self.socketMap[s][0](sock, addr)
                try:
                    self.postHandle()
                except:
                    self.logInterface.ERROR('postHandle died %s %s %s' %
                                            sys.exc_info())

            except:
                self.logInterface.ERROR(
                    "handler %s died with exception info %s" %
                    (self.socketMap[s][0], sys.exc_info()))
                self.logInterface.logException()
            sock.close()
            if r:
                self.logInterface.LOG('SM exiting due to r being true') 
                break
                
    def run(self):
        try:
            self._run()
        except:
            self.logInterface.ERROR("BUG! %s, %s, %s" % sys.exc_info())
            out = cStringIO.StringIO()
            traceback.print_tb(sys.exc_info()[2], file=out)
            self.logInterface.ERROR(out.getvalue())
            raise
        
    def reload(self):
        ProcessMgr.ProcessMgr.ProcessMgr.reload(self)
        self._reset()

    def retrying_bind(self, sock, addr, retries):
        retrycount = retries # mayhap it's not quite dead, so retry a few times
        while retrycount:
            try:
                sock.bind(addr)
            except:
                retrycount = retrycount - 1
                if retrycount == 0:
                    raise
                time.sleep(1)
            else:
                break
        
    def addConnection(self, addrspec, handler_func):
        if addrspec[0] == 'TCP':
            s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
            s.setblocking(0)
            s.setsockopt (socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
            # Make sure the socket will be closed on exec
            fcntl.fcntl (s.fileno(), FCNTL.F_SETFD, 1)
            self.retrying_bind(s, addrspec[1:], 5)
            s.listen(socket.SOMAXCONN)
        elif addrspec[0] == 'UNIX':
            try:
                pathstat=os.stat(addrspec[1])
            except OSError:
                pathstat=None
            if pathstat:
                # oops, file exists; is it a UNIX socket?
                if stat.S_ISSOCK(pathstat[0]):
                    # yes, delete it and start over;
                    # let any exception propagate
                    os.unlink(addrspec[1])
                else:
                    # if you've got something else there,
                    # I'm not going to delete it.
                    raise IOError, \
                          "file exists where unix "\
                          "socket is to be created: %s" % addrspec[1]
                    
            s = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
            s.setblocking(0)
            # Make sure the socket will be closed on exec
            fcntl.fcntl(s.fileno(), FCNTL.F_SETFD, 1)
            self.retrying_bind(s, addrspec[1], 5)
                    
            if len(addrspec) == 3:
                os.chmod(addrspec[1], addrspec[2])
            s.listen(socket.SOMAXCONN)
        else:
            raise ValueError, "unknown bind address type"
        self.socketMap[s] = handler_func, addrspec
            
    def stop(self):
        self._reset()

    def _reset(self):
        for k, (f, a) in self.socketMap.items():
            k.close()
            if a[0] == 'UNIX':
                try:
                    os.remove(a[1])
                except:
                    self.logInterface.ERROR(('removal of unix socket %s '
                                             'failed, continuing and hoping'
                                             ' for the best') % a[1])

        self.socketMap = {}
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.