python - 'Port' object has no attribute 'socket' -
i'm using twisted python make simple ssh server on custom port. create port object port = reactor.listentcp(_port, sshfactory)
, _port variable holds integer of port. free port when shutting down server commands port.loseconnection()
, port.connectionlost(reason=none)
. if attempt start server, stop it, , start again, titular error 'port' object has no attribute 'socket'
edit: full error message:
unhandled error in deferred: traceback (most recent call last): file "c:\python27\lib\site-packages\twisted\internet\base.py", line 1175, in mainloop self.rununtilcurrent() file "c:\python27\lib\site-packages\twisted\internet\base.py", line 779, in rununtilcurrent call.func(*call.args, **call.kw) file "c:\python27\lib\site-packages\twisted\internet\defer.py", line 238, in callback self._startruncallbacks(result) file "c:\python27\lib\site-packages\twisted\internet\defer.py", line 307, in _startruncallbacks self._runcallbacks() --- <exception caught here> --- file "c:\python27\lib\site-packages\twisted\internet\defer.py", line 323, in _runcallbacks self.result = callback(self.result, *args, **kw) file "c:\python27\lib\site-packages\twisted\internet\task.py", line 736, in <lambda> d.addcallback(lambda ignored: callable(*args, **kw)) file "c:\python27\lib\site-packages\twisted\internet\tcp.py", line 981, in connectionlost self._closesocket() file "c:\python27\lib\site-packages\twisted\internet\tcp.py", line 92, in _closesocket skt = self.socket exceptions.attributeerror: 'port' object has no attribute 'socket'
edit2: stoplistening code sample (python 2.7):
stoplistening sample.py
from twisted.cred import portal, checkers, credentials twisted.conch import error, avatar, recvline, interfaces conchinterfaces twisted.conch.ssh import factory, userauth, connection, keys, session, common twisted.conch.insults import insults twisted.application import service, internet twisted.internet import reactor, protocol zope.interface import implements import threading import os class sshdemoprotocol(recvline.historicrecvline): def __init__(self, user): self.user = user def connectionmade(self): recvline.historicrecvline.connectionmade(self) self.showprompt() def showprompt(self): self.terminal.write("$ ") class sshdemorealm: implements(portal.irealm) def requestavatar(self, avatarid, mind, *interfaces): if conchinterfaces.iconchuser in interfaces: return interfaces[0], sshdemoavatar(avatarid), lambda: none else: raise exception("no supported interfaces found.") def getrsakeys(): if not (os.path.exists('public.key') , os.path.exists('private.key')): # generate rsa keypair print("generating rsa keypair...") crypto.publickey import rsa key_length = 1024 rsakey = rsa.generate(key_length, common.entropy.get_bytes) publickeystring = keys.makepublickeystring(rsakey) privatekeystring = keys.makeprivatekeystring(rsakey) # save keys next time file('public.key', 'w+b').write(publickeystring) file('private.key', 'w+b').write(privatekeystring) print("done.") else: publickeystring = file('public.key').read() privatekeystring = file('private.key').read() return publickeystring, privatekeystring def launchserver(): _port = 4564 password = 'password' sshfactory = factory.sshfactory() sshfactory.portal = portal.portal(sshdemorealm()) users = {'user': password} sshfactory.portal.registerchecker( checkers.inmemoryusernamepassworddatabasedontuse(**users)) pubkeystring, privkeystring = getrsakeys() sshfactory.publickeys = { 'ssh-rsa': keys.getpublickeystring(data=pubkeystring)} sshfactory.privatekeys = { 'ssh-rsa': keys.getprivatekeyobject(data=privkeystring)} global port port = reactor.listentcp(_port, sshfactory) reactor.addsystemeventtrigger('before', 'shutdown', stopserver) reactor.run(installsignalhandlers=false) def startserver(): thread = threading.thread(target=launchserver) thread.start() def stopserver(): global port port.stoplistening() reactor.stop() reactor.crash() startserver() stopserver() startserver()
traceback:
>>> exception in thread thread-2: traceback (most recent call last): file "/usr/lib/python2.7/threading.py", line 552, in __bootstrap_inner self.run() file "/usr/lib/python2.7/threading.py", line 505, in run self.__target(*self.__args, **self.__kwargs) file "/home/paul/desktop/down2home/stoplistening sample.py", line 62, in launchserver port = reactor.listentcp(_port, sshfactory) file "/usr/local/lib/python2.7/dist-packages/twisted-9.0.0-py2.7-linux-x86_64.egg/twisted/internet/posixbase.py", line 355, in listentcp p.startlistening() file "/usr/local/lib/python2.7/dist-packages/twisted-9.0.0-py2.7-linux-x86_64.egg/twisted/internet/tcp.py", line 855, in startlistening raise cannotlistenerror, (self.interface, self.port, le) cannotlistenerror: couldn't listen on any:4564: [errno 98] address in use.
listentcp
returns ilisteningport
; ilisteningport
not have loseconnection
or connectionlost
methods. instead, has stoplistening
. presence of methods you're calling unfortunate accident. should try using publicly advertised interfaces , see if works.
(also, should post completely runnable bit of code, know mean "stop , start again", complete traceback, rather snippet of error message.)
additionally, twisted apis may not invoked arbitrary threads. code provoke undefined , difficult predict behavior twisted:
def stopserver(): global port port.stoplistening() reactor.stop() reactor.crash()
for several reasons. first, startserver
set application , started reactor in thread. means port.stoplistening()
not allowed because it's twisted api being called in wrong thread. second, reactor.crash()
testing helper, , in area, use discouraged better testing techniques have been developed since reactor.crash()
invented.
you might away fix these problems:
from twisted.internet.threads import blockingcallfromthread def startserver(): global thread thread = threading.thread(target=launchserver) thread.start() def stopserver(): global port, thread blockingcallfromthread(reactor, port.stoplistening) reactor.callfromthread(reactor.stop) thread.join() thread = none
of course, use of globals isn't ideal, i'm sticking them here keep code close original.
what is:
- call port.stoplistening in reactor thread using
blockingcallfromthread
. additionally, block untildeferred
returnedstoplistening
fires. means when line done, port no longer in use. - call reactor.stop in reactor thread using
reactor.callfromthread
. since call intended stop reactor, don't think it's safe useblockingcallfromthread
since once reactor stops inter-thread communication mechanism may no longer work. also,reactor.stop
doesn't returndeferred
there's nothing useful block on anyway. - wait reactor stop running joining thread in running (which block until
launchserver
returns,reactor.run()
returns, once reactor stops).
however, may want consider not using threads @ in way. there's no particular reason so, @ least none can determine minimal example. if have other use of threads seems necessary you, might make fodder question. :)
Comments
Post a Comment