Jajcus / pyxmpp

XMPP implementation for Python
http://pyxmpp.jajcus.net/
GNU Lesser General Public License v2.1
28 stars 9 forks source link

In certain cases pyxmpp eats exceptions #14

Open Jajcus opened 13 years ago

Jajcus commented 13 years ago

xmlextra.endElement() eats exceptions, instead of letting them propagate.

While it's bad style to let exceptions get away from callbacks, it may happen and then errors don't get reported. In my case an unexpected UnicodeEncodeError from pyxmpp code itself wasn't caught in my code, wreaked some havoc and vanished without a trace. Not a pleasant thing to debug.

Relevant part of a stack from my case to illustrate the issue:

{{{ File "/home/karol/programowanie/pyxmpp/pyxmpp/xmlextra.py", line 214, in endElement self._handler.stanza(self._doc, node1) File "/home/karol/programowanie/pyxmpp/pyxmpp/streambase.py", line 401, in stanza self._process_node(node) File "/home/karol/programowanie/pyxmpp/pyxmpp/stream.py", line 107, in _process_node StreamBase._process_node(self,xmlnode) File "/home/karol/programowanie/pyxmpp/pyxmpp/streambase.py", line 710, in _process_node self.process_stanza(stanza) File "/home/karol/programowanie/pyxmpp/pyxmpp/stanzaprocessor.py", line 274, in process_stanza if self.process_message(stanza): File "/home/karol/programowanie/pyxmpp/pyxmpp/stanzaprocessor.py", line 209, in process_message return self.__try_handlers(self._message_handlers,"normal",stanza) File "/home/karol/programowanie/pyxmpp/pyxmpp/stanzaprocessor.py", line 185, in try_handlers response = handler(stanza) File "/home/karol/programowanie/soc/tmp/jabberbot/xmppbot.py", line 372, in handle_message response = self.handle_internal_command(sender, command) File "/home/karol/programowanie/soc/tmp/jabberbot/xmppbot.py", line 402, in handle_internal_command self.send_search_form(sender) File "/home/karol/programowanie/soc/tmp/jabberbot/xmppbot.py", line 319, in send_search_form message.add_content(form) File "/home/karol/programowanie/pyxmpp/pyxmpp/stanza.py", line 303, in add_content content.as_xml(parent = self.xmlnode, doc = common_doc) File "/home/karol/programowanie/pyxmpp/pyxmpp/objects.py", line 91, in as_xml self.complete_xml_element(xmlnode, doc1) File "/home/karol/programowanie/pyxmpp/pyxmpp/jabber/dataforms.py", line 632, in complete_xml_element xmlnode.newTextChild(ns, "title", self.title) File "/usr/lib64/python2.3/site-packages/libxml2.py", line 3325, in newTextChild ret = libxml2mod.xmlNewTextChild(self._o, nso, name, content) UnicodeEncodeError: 'ascii' codec can't encode character u'\u015b' in position 2: ordinal not in range(128) }}}

Jajcus commented 13 years ago

i have rewritten the xmlextra.endElement() function so that it does not eat error propagation. the described behaviour resulted from the extensive use of 'finally' statements in error trapping.

please take this WITH CAUTION as i have not fully tested it, however it does seem to solve my issues.

anyone trying this out please let the community and jajcus if this can be officially set in the svn rep.

the rewritten function can be seen here below, and i have attached the complete file for your convenience.

{{{

    def endElement(self, tag):
        ""
        self._current+="</%s>" % (tag,)
        self._level -= 1
        if self._level > 1:
            return
        if self._level==1:
            xml=self._head+self._current+self._tail
            doc=libxml2.parseDoc(xml)
            try:
                node = doc.getRootElement().children
            except:
                doc.freeDoc()
                return
            try:
                node1 = node.docCopyNode(self._doc, 1)
            except:
                del node
                doc.freeDoc()
                return
            try:
                self._root.addChild(node1)
            except:
                node1.unlinkNode()
                node1.freeNode()
                del node1
                del node
                doc.freeDoc()
            try:
                self._handler.stanza(self._doc, node1)
            except:
                node1.unlinkNode()
                node1.freeNode()
                del node1
                del node
                doc.freeDoc()
                raise
            del node1
            del node
            doc.freeDoc()
        else:
            xml=self._head+self._tail
            doc=libxml2.parseDoc(xml)
            try:
                self._handler.stream_end(self._doc)
                self._doc.freeDoc()
                self._doc = None
                self._root = None
            finally:
                doc.freeDoc()

}}}

--roberto ostinelli

Jajcus commented 13 years ago

forgot a return statement

{{{ def endElement(self, tag): "" self._current+="</%s>" % (tag,) self._level -= 1 if self._level > 1: return if self._level==1: xml=self._head+self._current+self._tail doc=libxml2.parseDoc(xml) try: node = doc.getRootElement().children except: doc.freeDoc() return try: node1 = node.docCopyNode(self._doc, 1) except: del node doc.freeDoc() return try: self._root.addChild(node1) except: node1.unlinkNode() node1.freeNode() del node1 del node doc.freeDoc() return try: self._handler.stanza(self._doc, node1) except: node1.unlinkNode() node1.freeNode() del node1 del node doc.freeDoc() raise del node1 del node doc.freeDoc() else: xml=self._head+self._tail doc=libxml2.parseDoc(xml) try: self._handler.stream_end(self._doc) self._doc.freeDoc() self._doc = None self._root = None finally: doc.freeDoc() }}}

--roberto ostinelli

Jajcus commented 13 years ago

I have tested with xmlextra.3.py, when the SASLAuthenticationFailed exception raised, it still can't work right. the exception was eation by xmlpaser. see the follow message:

File "C:\Python25\Lib\site-packages\pyxmpp\xmlextra.py", line 229, in endElement self._handler.stanza(self._doc, node1) File "C:\Python25\Lib\site-packages\pyxmpp\streambase.py", line 402, in stanza self._process_node(node) File "C:\Python25\Lib\site-packages\pyxmpp\stream.py", line 105, in _process_node if self._process_node_sasl(xmlnode): File "C:\Python25\lib\site-packages\pyxmpp\streamsasl.py", line 102, in _process_node_sasl self._process_sasl_node(xmlnode) File "C:\Python25\lib\site-packages\pyxmpp\streamsasl.py", line 121, in _process_sasl_node ret=self._process_sasl_failure(xmlnode) File "C:\Python25\lib\site-packages\pyxmpp\streamsasl.py", line 322, in _process_sasl_failure raise SASLAuthenticationFailed,"SASL authentication failed" pyxmpp.exceptions.SASLAuthenticationFailed: SASL authentication failed

--anonymous

Jajcus commented 13 years ago

SASLAuthenticationFailed exception can be handled right in pyxmpp 1.0.1. I have tested it in win32 platform.

--anonymous

Jajcus commented 13 years ago

Assuming (assumption based on the last comment) it is fixed.

--jajcus

Jajcus commented 13 years ago

The same problem still happens (Ubuntu lucid, PyXMPP version 1.1.1) - this exception doesn't seem to be propagated upwards. Also tested with the fixes mentioned previously in this ticket - to no avail.

Traceback (most recent call last): File "../pyxmpp/xmlextra.py", line 225, in endElement self._handler.stanza(self._doc, node1) File "../pyxmpp/streambase.py", line 401, in stanza self._process_node(node) File "../pyxmpp/stream.py", line 105, in _process_node if self._process_node_sasl(xmlnode): File "../pyxmpp/streamsasl.py", line 102, in _process_node_sasl self._process_sasl_node(xmlnode) File "../pyxmpp/streamsasl.py", line 121, in _process_sasl_node ret=self._process_sasl_failure(xmlnode) File "../pyxmpp/streamsasl.py", line 322, in _process_sasl_failure raise SASLAuthenticationFailed,"SASL authentication failed" pyxmpp.exceptions.SASLAuthenticationFailed: SASL authentication failed

--adamk

bkjones commented 13 years ago

I have the same problem with the SASLAuthenticationFailed issue. Any clues to help narrow the scope of the investigation into finding a fix are much appreciated.