summaryrefslogtreecommitdiff
path: root/monserver.py
blob: 26fe959ee0fa21ad1baef1edf3904cc4e36e918d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
# -*- coding: utf-8 -*-
"""A TCP server implemented in a separate thread that
allows *one* client to connect and provides a command line interpreter
allowing the remote client to explore the process on the fly.

:copyright: 2000-2008 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
:contact: http://www.logilab.fr/ -- mailto:contact@logilab.fr
:license: General Public License version 2 - http://www.gnu.org/licenses
"""
__docformat__ = "restructuredtext en"

from warnings import warn
warn('this module is deprecated and will disappear in a near release',
     DeprecationWarning, stacklevel=1)

import threading
import SocketServer
import traceback
import code
import sys
import time

# NOTES: ce module étant utilisé pour l'introspection, il peut
# être utile de fournir dans les locales de l'interpreteur des
# objets déjà initialisés (par exemple le module __main__ ou
# bien __main__.*) ou encore des objets servant à l'introspection
# comme on en trouve dans pymonitor (qui prend la liste des objets
# maintenus par le garbage collector) ou a des statistiques
# pour faire des opérations du style:
# inspector.count_types( MyClass )
# inspector.list_types( MyClass ) etc...

class MonitorInterpreter(code.InteractiveConsole):
    """Subclasses InteractiveConsole so that all inputs
    and outputs are done through a socket"""
    def __init__(self, rfile, wfile ):
        code.InteractiveConsole.__init__(self)
        self.wfile = wfile
        self.rfile = rfile
        sys.stdout = self.wfile
        sys.stderr = self.wfile

    def write(self, data):
        """replace stderr output by writing to wfile"""
        self.wfile.write( data )
        self.wfile.flush()

    def raw_input( self, prompt = None ):
        """Provides reading lines through the network"""
        if prompt is not None:
            self.wfile.write(prompt)
            self.wfile.flush()
        line = self.rfile.readline()
        if line.endswith("\r\n"):
            line = line[:-2]
        elif line.endswith("\n"):
            line = line[:-1]
        return line
        

class MonitorRequestHandler(SocketServer.BaseRequestHandler):
    """Request handler for remote interpreter"""
    def __init__(self, request, clientaddress, server ):
        self.locals = {}
        self.globals = globals().copy()
        self.wfile = request.makefile("w")
        self.rfile = request.makefile("r")
        SocketServer.BaseRequestHandler.__init__(self, request, clientaddress,
                                                 server )
        
    def handle(self):
        """handle on request, through MonitorInterpreter"""
        saved_stdout = sys.stdout
        saved_stderr = sys.stderr
        interpreter = MonitorInterpreter(self.rfile, self.wfile)
        try:
            interpreter.interact()
        except KeyboardInterrupt:
            self.server.exit = True
        except:
            sys.stdout = saved_stdout
            sys.stderr = saved_stderr
            traceback.print_exc()
        print "Monitor handler exited"

class Monitor(threading.Thread):
    """Monitor server. monothreaded we only
    allow one client at a time"""
    def __init__(self, host, port):
        threading.Thread.__init__(self)
        self.host = host
        self.port = port
        self.exit = False


    def run(self):
        """run the server loop"""
        server = SocketServer.TCPServer( (self.host, self.port),
                                         MonitorRequestHandler )
        while not self.exit:
            server.handle_request()



def demo_forever():
    """sample demo server that outputs
    numbers on screen"""
    cnt = 1
    while 1:
        print cnt
        time.sleep(2)
        cnt += 1

if __name__ == "__main__":
    listen_port = int(sys.argv[1])
    mon = Monitor( "", listen_port )
    mon.start()
    try:
        demo_forever()
    except Exception:
        traceback.print_exc()
    mon.exit = True
    mon.join()