Denis Bilenko avatar Denis Bilenko committed 1241873

examples/portforwarder.py: add __docstring__, treat multiple signals as "exit now" request.

Do not handle QUIT, let Ctrl-\ work. Do not print stacktrace if target cannot be connected to.

Comments (0)

Files changed (1)

examples/portforwarder.py

+"""Port forwarder with graceful exit.
+
+Run the example as
+
+  python portforwarder.py :8080 gevent.org:80
+
+Then direct your browser to http://localhost:8080 or do "telnet localhost 8080".
+
+When the portforwarder receives TERM or INT signal (type Ctrl-C),
+it closes the listening socket and waits for all existing
+connections to finish. The existing connections will remain unaffected.
+The program will exit once the last connection has been closed.
+"""
 import sys
 import signal
 import gevent
 
     def handle(self, source, address):
         log('%s:%s accepted', *address[:2])
-        dest = create_connection(self.dest)
-        forwarder1 = gevent.spawn(forward, source, dest)
-        forwarder2 = gevent.spawn(forward, dest, source)
-        gevent.joinall([forwarder1, forwarder2], count=1)
+        try:
+            dest = create_connection(self.dest)
+        except IOError, ex:
+            log('%s:%s failed to connect to %s:%s: %s', address[0], address[1], self.dest[0], self.dest[1], ex)
+            return
+        gevent.spawn(forward, source, dest)
+        gevent.spawn(forward, dest, source)
 
     def close(self):
-        print 'Closing listener socket'
-        StreamServer.close(self)
+        if self.closed:
+            sys.exit('Multiple exit signals received - aborting.')
+        else:
+            log('Closing listener socket')
+            StreamServer.close(self)
 
 
 def forward(source, dest):
     server = PortForwarder(source, dest)
     log('Starting port forwarder %s:%s -> %s:%s', *(server.address[:2] + dest))
     gevent.signal(signal.SIGTERM, server.close)
-    gevent.signal(signal.SIGQUIT, server.close)
     gevent.signal(signal.SIGINT, server.close)
     server.start()
     gevent.run()
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.