tamentis / rpdb

Wrapper around pdb allowing remote debugging via netcat or telnet. This is especially useful in a Tomcat/Jython environment where little debugging tools are available.
BSD 2-Clause "Simplified" License
130 stars 44 forks source link

Overriding sys.stdin causes errors in processes that actually uses attributes of sys.stdin #21

Open MarounMaroun opened 7 years ago

MarounMaroun commented 7 years ago

In one of my projects I used sys.stdin.encoding, but since in this project we have:

sys.stdout = sys.stdin = handle

I got an exception during runtime.

Can we have a default values for that attribute (or even have the ability to pass its attribute in the constructor)?

(I can submit a PR if it's relevant)

dougszumski commented 7 years ago

+1 for a default. I'm using rpdb to debug an OpenStack service which uses oslo.utils. oslo.utils has the following:

> /usr/lib/python2.7/site-packages/oslo_utils/encodeutils.py(39)safe_decode() 
-> incoming = (sys.stdin.encoding or                                          
(Pdb) l                                                                       
 34                                                                           
 35         if isinstance(text, six.text_type):                               
 36             return text                                                   
 37                                                                           
 38         if not incoming:                                                  
 39  ->         incoming = (sys.stdin.encoding or                             
 40                         sys.getdefaultencoding())                         
 41                                                                           
 42         try:                                                              
 43             return text.decode(incoming, errors)                          
 44         except UnicodeDecodeError:                                        
(Pdb) type(sys.stdin)                                                         
<class 'rpdb.FileObjectWrapper'>

When this executes I see the following error:

AttributeError: "'_fileobject' object has no attribute 'encoding'"

The code runs fine outside rpdb because sys.stdin.encoding is defined.

MarounMaroun commented 7 years ago

@dougszumski Well, that's exactly what I'm having now (also while debugging an OpenStack service). A workaround would be adding the encoding attribute to sys.stdin just a line before it breaks.

I'm still waiting for a response from OP before submitting my PR.

tamentis commented 7 years ago

Yes that makes sense, I'll gladly review that PR.

tamentis commented 7 years ago

I'm not sure how this is happening since the point of rpdb.FileObjectWrapper is to allow you to access properties such as encoding.

@MarounMaroun are you using 0.1.6?

@dougszumski could you check the type of sys.stdin._io and sys.stdin._obj?

MarounMaroun commented 7 years ago

@tamentis Yes, I'm on 0.1.6.

MarounMaroun commented 7 years ago

@tamentis The solution should look something like this, can you please take a look?

@dougszumski FYI.

dougszumski commented 7 years ago

Here's a bit more info:

> /usr/lib/python2.7/site-packages/oslo_utils/encodeutils.py(38)safe_decode()
-> if not incoming:
(Pdb) l
 33             raise TypeError("%s can't be decoded" % type(text))
 34
 35         if isinstance(text, six.text_type):
 36             return text
 37         import rpdb; rpdb.set_trace()
 38  ->     if not incoming:
 39             incoming = (sys.stdin.encoding or
 40                         sys.getdefaultencoding())
 41
 42         try:
 43             return text.decode(incoming, errors)
(Pdb) rpdb.__version__
'0.1.6'
(Pdb) sys.stdin._io
<open file '<stdin>', mode 'r' at 0x7f2d6d3720c0>
(Pdb) sys.stdin._obj
<socket._fileobject object at 0x239d450>
(Pdb) sys.stdin.encoding
'UTF-8'
(Pdb) n
> /usr/lib/python2.7/site-packages/oslo_utils/encodeutils.py(39)safe_decode()
-> incoming = (sys.stdin.encoding or
(Pdb)
AttributeError: "'_fileobject' object has no attribute 'encoding'"
> /usr/lib/python2.7/site-packages/oslo_utils/encodeutils.py(39)safe_decode()
-> incoming = (sys.stdin.encoding or
(Pdb) sys.stdin.encoding
'UTF-8'
(Pdb) sys.getdefaultencoding()
'ascii'
dougszumski commented 7 years ago

Ah, I think I see what's happening:

> /usr/lib/python2.7/site-packages/oslo_utils/encodeutils.py(38)safe_decode()
-> if not incoming:
(Pdb) l
 33             raise TypeError("%s can't be decoded" % type(text))
 34
 35         if isinstance(text, six.text_type):
 36             return text
 37         import rpdb; rpdb.set_trace()
 38  ->     if not incoming:
 39             incoming = (sys.stdin.encoding or
 40                         sys.getdefaultencoding())
 41
 42         try:
 43             return text.decode(incoming, errors)
(Pdb) sys.stdin._obj
<socket._fileobject object at 0x1a2a450>
(Pdb) sys.stdin._obj.encoding
*** AttributeError: '_fileobject' object has no attribute 'encoding'
(Pdb) sys.stdin._io.encoding
'UTF-8'

Looks like this happens in FileObjectWrapper:

class FileObjectWrapper(object):
    def __init__(self, fileobject, stdio):
        self._obj = fileobject
        self._io = stdio

    def __getattr__(self, attr):
        if hasattr(self._obj, attr):
            attr = getattr(self._obj, attr)
        elif hasattr(self._io, attr):
            attr = getattr(self._io, attr)
        else:
            raise AttributeError("Attribute %s is not found" % attr)
        return attr
MarounMaroun commented 7 years ago

@dougszumski good point. So the solution I suggested didn't work for you?

Boris-Barboris commented 7 years ago

Why was stdin\out assignment needed in the first place? I just commented them out and everything worked fine.

MarounMaroun commented 7 years ago

@Boris-Barboris Which lines did you comment out?

Boris-Barboris commented 7 years ago

@MarounMaroun https://github.com/tamentis/rpdb/blob/master/rpdb/__init__.py#L61 https://github.com/tamentis/rpdb/blob/master/rpdb/__init__.py#L67 and 68

airborne007 commented 5 years ago

Hi, everyone, is this problem solved? I also encountered this problem when debugging the OpenStack project.

MarounMaroun commented 5 years ago

@airborne007 Not yet. The current solution is to add encoding attribute to sys.stdin just a line before it breaks.