title: how do I avoid the infinite loop when using the paramiko port forward demo?
body: <p>I need use port forwarding in Python to communicate with a remote MySQL DB through an SSH tunnel. I downloaded the paramiko package and tried out the port forwarding demo (forward.py). It works very nicely, but I am having trouble integrating it into my own scripts (similar to the one below). When the main forwarding function is called it enters an infinite loop and the rest of my code does not execute. How can I use the forward.py demo and get past the infinite loop?</p>
  
  <p>My script:</p>
  
  <pre><code>import paramiko
  import forward
  import MySQLdb
  import cfg
  import sys
  
  client = paramiko.SSHClient()
  client.load_system_host_keys()
  client.set_missing_host_key_policy(paramiko.WarningPolicy())
  
  try:
      client.connect(cfg.remhost, cfg.remport, username=cfg.user, password=cfg.password)
  except Exception, e:
      print '*** Failed to connect to %s:%d: %r' % (cfg.remhost, cfg.remport, e)
      sys.exit(1)
  
  
  try:
      forward.forward_tunnel(3306, cfg.remhost, 3306, client.get_transport())
  except KeyboardInterrupt:
      print 'C-c: Port forwarding stopped.'
      sys.exit(0)
  
  try:
      db = MySQLdb.connect('127.0.0.1', cfg.dbuser, cfg.dbpass, cfg.dbname)
  except Exception, e:
      print 'Failed to connect to database'
      sys.exit(1)
  
  try:
      cursor = self.db.cursor(MySQLdb.cursors.DictCursor)
      sql = 'SELECT * FROM  ' + cfg.dbtable
      cursor.execute(sql)
      results = cursor.fetchall()
      print str(len(results))
  except Exception, e:
      print 'Failed to query database'
      sys.exit(1)
  </code></pre>
  
  <p>Here is the main chunk of the forward.py demo code:</p>
  
  <pre><code>class ForwardServer (SocketServer.ThreadingTCPServer):
      daemon_threads = True
      allow_reuse_address = True
  
  
  class Handler (SocketServer.BaseRequestHandler):
  
      def handle(self):
          try:
              chan = self.ssh_transport.open_channel('direct-tcpip',
                                                     (self.chain_host, self.chain_port),
                                                     self.request.getpeername())
          except Exception, e:
              verbose('Incoming request to %s:%d failed: %s' % (self.chain_host,
                                                                self.chain_port,
                                                                repr(e)))
              return
          if chan is None:
              verbose('Incoming request to %s:%d was rejected by the SSH server.' %
                      (self.chain_host, self.chain_port))
              return
  
          verbose('Connected!  Tunnel open %r -&gt; %r -&gt; %r' % (self.request.getpeername(),
                                                              chan.getpeername(), (self.chain_host, self.chain_port)))
          while True:
              r, w, x = select.select([self.request, chan], [], [])
              if self.request in r:
                  data = self.request.recv(1024)
                  if len(data) == 0:
                      break
                  chan.send(data)
              if chan in r:
                  data = chan.recv(1024)
                  if len(data) == 0:
                      break
                  self.request.send(data)
          chan.close()
          self.request.close()
          verbose('Tunnel closed from %r' % (self.request.getpeername(),))
  
  
  def forward_tunnel(local_port, remote_host, remote_port, transport):
      # this is a little convoluted, but lets me configure things for the Handler
      # object.  (SocketServer doesn't give Handlers any way to access the outer
      # server normally.)
      class SubHander (Handler):
          chain_host = remote_host
          chain_port = remote_port
          ssh_transport = transport
      ForwardServer(('', local_port), SubHander).serve_forever()
  
  
  def verbose(s):
      if g_verbose:
          print s
  </code></pre>