Re: [lldb-dev] LLDB: Unwinding based on Assembly Instruction Profiling

2015-10-15 Thread Tamas Berghammer via lldb-dev
If we are trying to unwind from a non call site (frame 0 or signal handler)
then the current implementation first try to use the non call site unwind
plan (usually assembly emulation) and if that one fails then it will fall
back to the call site unwind plan (eh_frame, compact unwind info, etc.)
instead of falling back to the architecture default unwind plan because it
should be a better guess in general and we usually fail with the assembly
emulation based unwind plan for hand written assembly functions where
eh_frame is usually valid at all address.

Generating asynchronous eh_frame (valid at all address) is possible with
gcc (I am not sure about clang) but there is no way to tell if a given
eh_frame inside an object file is valid at all address or only at call
sites. The best approximation what we can do is to say that each eh_frame
entry is valid only at the address what it specifies as start address but
we don't make a use of it in LLDB at the moment.

For the 2nd part of the original question, I think changing the eh_frame
based unwind plan after a failed unwind using instruction emulation is only
a valid option for the PC where we tried to unwind from because the
assembly based unwind plan could be valid at other parts of the function.
Making the change for that 1 concrete PC address would make sense, but have
practically no effect because the next time we want to unwind from the
given address we use the same fall back mechanism as in the first case and
the change would have only a very small performance gain.

Tamas

On Wed, Oct 14, 2015 at 9:36 PM Greg Clayton via lldb-dev <
lldb-dev@lists.llvm.org> wrote:

>
> > On Oct 14, 2015, at 1:02 PM, Joerg Sonnenberger via lldb-dev <
> lldb-dev@lists.llvm.org> wrote:
> >
> > On Wed, Oct 14, 2015 at 11:42:06AM -0700, Greg Clayton via lldb-dev
> wrote:
> >> EH frame can't be used to unwind when we are in the first frame because
> >> it is only valid at call sites. It also can't be used in frames that
> >> are asynchronously interrupted like signal handler frames.
> >
> > This is not necessarily true, GCC can build them like that. I don't
> > think we have a flag for clang/LLVM to create full async unwind tables.
>
> Most compilers don't generate stuff that is complete, and if it is
> complete, I am not aware of any markings on EH frame that states it is
> complete. So we really can't use it unless we know the info is complete.
> Was there ever an additional augmentation letter that was attached to the
> complete EH frame info?
>
>
> ___
> lldb-dev mailing list
> lldb-dev@lists.llvm.org
> http://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-dev
>
___
lldb-dev mailing list
lldb-dev@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-dev


Re: [lldb-dev] Question on assert

2015-10-15 Thread Tamas Berghammer via lldb-dev
Hi Todd,

The 64 bit ID of a DIE is built up in the following way:
* The offset of the DIE is in the lower 32 bit
* If we are using SymbolFileDWARF then the higher 32 bit is the offset of
the compile unit this DIE belongs to
* If we are using SymbolFileDWARFDwo then the higher 32 bit is the offset
of the base compile unit in the parent SymbolFileDWARF
* If we are using SymbolFileDWARFDebugMap then the higher 32 bit is the ID
of the SymbolFileDWARF this DIE belongs to
* If the higher 32 bit is 0 then that means that the source of the DIE
isn't specified

The assert then tries to verify that one of the following conditions holds:
* The higher 32 bit of "id" is 0 what means that we don't have a symbol
file pointer (AFAIK shouldn't happen) or we are coming from a
SymbolFileDWARF
* The higher 32 bit of "cu_id" is 0 what means that the compile unit is at
0 offset what is the case for the single compile units in
SymbolFileDWARFDwo (and I think for SymbolFileDWARFDebugMap)
* The higher 32 bit of "id" (what is the ID of the SymbolFileDWARF we are
belonging to) matches with the higher 32 bit of "cu_id" (what is the offset
of the compile unit in the base object file)

After thinking a bit more about the assert I think the problem is that the
way I calculate cu_id is incompatible for the case when we are using
SymbolFileDWARFDebugMap.

I think changing line 188 to the following should fix the issue:
lldb::user_id_t cu_id = m_cu->GetID()&0xull;

Please give it a try on OSX and let me know if it helps. I tested it on
Linux and it isn't cause any regression there.

Thanks,
Tamas

On Wed, Oct 14, 2015 at 9:13 PM Todd Fiala  wrote:

> Hi Tamas,
>
> There is an assert in DWARFDIE.cpp (lines 189 - 191) that we're hitting on
> the OS X side somewhat frequently nowadays:
>
> assert ((id&0xull) == 0 ||
>
> (cu_id&0xll) == 0 ||
>
> (id&0xull) == (cu_id&
> 0xll));
>
>
> It does not seem to get hit consistently.  We're trying to tease apart
> what it is trying to do.  It's a bit strange since it is saying that the
> assert should not fire if any one of three clauses is true.  But it's hard
> to figure out what exactly is going on there.
>
>
> Can you elucidate what this is trying to do?  Thanks!
>
> --
> -Todd
>
___
lldb-dev mailing list
lldb-dev@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-dev


Re: [lldb-dev] Question on assert

2015-10-15 Thread Todd Fiala via lldb-dev
Okay!  I'll give that a shot now and report back what I find.

Thanks, Tamas :-)

-Todd

On Thu, Oct 15, 2015 at 3:37 AM, Tamas Berghammer 
wrote:

> Hi Todd,
>
> The 64 bit ID of a DIE is built up in the following way:
> * The offset of the DIE is in the lower 32 bit
> * If we are using SymbolFileDWARF then the higher 32 bit is the offset of
> the compile unit this DIE belongs to
> * If we are using SymbolFileDWARFDwo then the higher 32 bit is the offset
> of the base compile unit in the parent SymbolFileDWARF
> * If we are using SymbolFileDWARFDebugMap then the higher 32 bit is the ID
> of the SymbolFileDWARF this DIE belongs to
> * If the higher 32 bit is 0 then that means that the source of the DIE
> isn't specified
>
> The assert then tries to verify that one of the following conditions holds:
> * The higher 32 bit of "id" is 0 what means that we don't have a symbol
> file pointer (AFAIK shouldn't happen) or we are coming from a
> SymbolFileDWARF
> * The higher 32 bit of "cu_id" is 0 what means that the compile unit is at
> 0 offset what is the case for the single compile units in
> SymbolFileDWARFDwo (and I think for SymbolFileDWARFDebugMap)
> * The higher 32 bit of "id" (what is the ID of the SymbolFileDWARF we are
> belonging to) matches with the higher 32 bit of "cu_id" (what is the offset
> of the compile unit in the base object file)
>
> After thinking a bit more about the assert I think the problem is that the
> way I calculate cu_id is incompatible for the case when we are using
> SymbolFileDWARFDebugMap.
>
> I think changing line 188 to the following should fix the issue:
> lldb::user_id_t cu_id = m_cu->GetID()&0xull;
>
> Please give it a try on OSX and let me know if it helps. I tested it on
> Linux and it isn't cause any regression there.
>
> Thanks,
> Tamas
>
> On Wed, Oct 14, 2015 at 9:13 PM Todd Fiala  wrote:
>
>> Hi Tamas,
>>
>> There is an assert in DWARFDIE.cpp (lines 189 - 191) that we're hitting
>> on the OS X side somewhat frequently nowadays:
>>
>> assert ((id&0xull) == 0 ||
>>
>> (cu_id&0xll) == 0 ||
>>
>> (id&0xull) == (cu_id&
>> 0xll));
>>
>>
>> It does not seem to get hit consistently.  We're trying to tease apart
>> what it is trying to do.  It's a bit strange since it is saying that the
>> assert should not fire if any one of three clauses is true.  But it's hard
>> to figure out what exactly is going on there.
>>
>>
>> Can you elucidate what this is trying to do?  Thanks!
>>
>> --
>> -Todd
>>
>


-- 
-Todd
___
lldb-dev mailing list
lldb-dev@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-dev


[lldb-dev] Python object lifetimes affect the reliability of tests

2015-10-15 Thread Adrian McCarthy via lldb-dev
I've tracked down a source of flakiness in tests on Windows to Python
object lifetimes and the SB interface, and I'm wondering how best to handle
it.

Consider this portion of a test from TestTargetAPI:

def find_functions(self, exe_name):
"""Exercise SBTaget.FindFunctions() API."""
exe = os.path.join(os.getcwd(), exe_name)

# Create a target by the debugger.
target = self.dbg.CreateTarget(exe)
self.assertTrue(target, VALID_TARGET)
list = target.FindFunctions('c', lldb.eFunctionNameTypeAuto)
self.assertTrue(list.GetSize() == 1)

for sc in list:
self.assertTrue(sc.GetModule().GetFileSpec().GetFilename() ==
exe_name)
self.assertTrue(sc.GetSymbol().GetName() == 'c')

The local variables go out of scope when the function exits, but the SB
(C++) objects they represent aren't (always) immediately destroyed.  At
least some of these objects keep references to the executable module in the
shared module list, so when the test framework cleans up and calls
`SBDebugger::DeleteTarget`, the module isn't orphaned, so LLDB maintains an
open handle to the executable.

The result of the lingering handle is that, when the next test case in the
test suite tries to re-build the executable, it fails because the file is
not writable.  (This is problematic on Windows because the file system
works differently in this regard than Unix derivatives.)  Every subsequent
case in the test suite fails.

I managed to make the test work reliably by rewriting it like this:

def find_functions(self, exe_name):
"""Exercise SBTaget.FindFunctions() API."""
exe = os.path.join(os.getcwd(), exe_name)

# Create a target by the debugger.
target = self.dbg.CreateTarget(exe)
self.assertTrue(target, VALID_TARGET)

try:
list = target.FindFunctions('c', lldb.eFunctionNameTypeAuto)
self.assertTrue(list.GetSize() == 1)

for sc in list:
try:

self.assertTrue(sc.GetModule().GetFileSpec().GetFilename() == exe_name)
self.assertTrue(sc.GetSymbol().GetName() == 'c')
finally:
del sc

finally:
del list

The finally blocks ensure that the corresponding C++ objects are destroyed,
even if the function exits as a result of a Python exception (e.g., if one
of the assertion expressions is false and the code throws an exception).
Since the objects are destroyed, the reference counts are back to where
they should be, and the orphaned module is closed when the target is
deleted.

But this is ugly and maintaining it would be error prone.  Is there a
better way to address this?

In general, it seems bad that our tests aren't well-isolated.  I sympathize
with the concern that re-starting LLDB for each test case would slow down
testing, but I'm also concerned that the state of LLDB for any given test
case can depend on what happened in the earlier cases.

Adrian.
___
lldb-dev mailing list
lldb-dev@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-dev


Re: [lldb-dev] Question on assert

2015-10-15 Thread Todd Fiala via lldb-dev
I'm re-running the tests to make sure, but I think that fixed it.  I had
always seen it at least once on test runs locally, but didn't see it on the
last one.

On Thu, Oct 15, 2015 at 8:10 AM, Todd Fiala  wrote:

> Okay!  I'll give that a shot now and report back what I find.
>
> Thanks, Tamas :-)
>
> -Todd
>
> On Thu, Oct 15, 2015 at 3:37 AM, Tamas Berghammer 
> wrote:
>
>> Hi Todd,
>>
>> The 64 bit ID of a DIE is built up in the following way:
>> * The offset of the DIE is in the lower 32 bit
>> * If we are using SymbolFileDWARF then the higher 32 bit is the offset of
>> the compile unit this DIE belongs to
>> * If we are using SymbolFileDWARFDwo then the higher 32 bit is the offset
>> of the base compile unit in the parent SymbolFileDWARF
>> * If we are using SymbolFileDWARFDebugMap then the higher 32 bit is the
>> ID of the SymbolFileDWARF this DIE belongs to
>> * If the higher 32 bit is 0 then that means that the source of the DIE
>> isn't specified
>>
>> The assert then tries to verify that one of the following conditions
>> holds:
>> * The higher 32 bit of "id" is 0 what means that we don't have a symbol
>> file pointer (AFAIK shouldn't happen) or we are coming from a
>> SymbolFileDWARF
>> * The higher 32 bit of "cu_id" is 0 what means that the compile unit is
>> at 0 offset what is the case for the single compile units in
>> SymbolFileDWARFDwo (and I think for SymbolFileDWARFDebugMap)
>> * The higher 32 bit of "id" (what is the ID of the SymbolFileDWARF we are
>> belonging to) matches with the higher 32 bit of "cu_id" (what is the offset
>> of the compile unit in the base object file)
>>
>> After thinking a bit more about the assert I think the problem is that
>> the way I calculate cu_id is incompatible for the case when we are using
>> SymbolFileDWARFDebugMap.
>>
>> I think changing line 188 to the following should fix the issue:
>> lldb::user_id_t cu_id = m_cu->GetID()&0xull;
>>
>> Please give it a try on OSX and let me know if it helps. I tested it on
>> Linux and it isn't cause any regression there.
>>
>> Thanks,
>> Tamas
>>
>> On Wed, Oct 14, 2015 at 9:13 PM Todd Fiala  wrote:
>>
>>> Hi Tamas,
>>>
>>> There is an assert in DWARFDIE.cpp (lines 189 - 191) that we're hitting
>>> on the OS X side somewhat frequently nowadays:
>>>
>>> assert ((id&0xull) == 0 ||
>>>
>>> (cu_id&0xll) == 0 ||
>>>
>>> (id&0xull) == (cu_id&
>>> 0xll));
>>>
>>>
>>> It does not seem to get hit consistently.  We're trying to tease apart
>>> what it is trying to do.  It's a bit strange since it is saying that the
>>> assert should not fire if any one of three clauses is true.  But it's hard
>>> to figure out what exactly is going on there.
>>>
>>>
>>> Can you elucidate what this is trying to do?  Thanks!
>>>
>>> --
>>> -Todd
>>>
>>
>
>
> --
> -Todd
>



-- 
-Todd
___
lldb-dev mailing list
lldb-dev@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-dev


Re: [lldb-dev] Python object lifetimes affect the reliability of tests

2015-10-15 Thread Oleksiy Vyalov via lldb-dev
I stumbled upon similar problem when was looking into why SBDebugger wasn't
unloaded upon app's exit.
The problem was in Python global objects like lldb.debugger, lldb.target
sitting around.
So, my guess is to try to call ScriptInterpreterPython::Clear  within
test's tearDown call - e.g., expose Clear method as part of
SBCommandInterpreter and call it via SBDebugger::GetCommandInterpreter

On Thu, Oct 15, 2015 at 8:50 AM, Adrian McCarthy via lldb-dev <
lldb-dev@lists.llvm.org> wrote:

> I've tracked down a source of flakiness in tests on Windows to Python
> object lifetimes and the SB interface, and I'm wondering how best to handle
> it.
>
> Consider this portion of a test from TestTargetAPI:
>
> def find_functions(self, exe_name):
> """Exercise SBTaget.FindFunctions() API."""
> exe = os.path.join(os.getcwd(), exe_name)
>
> # Create a target by the debugger.
> target = self.dbg.CreateTarget(exe)
> self.assertTrue(target, VALID_TARGET)
> list = target.FindFunctions('c', lldb.eFunctionNameTypeAuto)
> self.assertTrue(list.GetSize() == 1)
>
> for sc in list:
> self.assertTrue(sc.GetModule().GetFileSpec().GetFilename() ==
> exe_name)
> self.assertTrue(sc.GetSymbol().GetName() == 'c')
>
> The local variables go out of scope when the function exits, but the SB
> (C++) objects they represent aren't (always) immediately destroyed.  At
> least some of these objects keep references to the executable module in the
> shared module list, so when the test framework cleans up and calls
> `SBDebugger::DeleteTarget`, the module isn't orphaned, so LLDB maintains an
> open handle to the executable.
>
> The result of the lingering handle is that, when the next test case in the
> test suite tries to re-build the executable, it fails because the file is
> not writable.  (This is problematic on Windows because the file system
> works differently in this regard than Unix derivatives.)  Every subsequent
> case in the test suite fails.
>
> I managed to make the test work reliably by rewriting it like this:
>
> def find_functions(self, exe_name):
> """Exercise SBTaget.FindFunctions() API."""
> exe = os.path.join(os.getcwd(), exe_name)
>
> # Create a target by the debugger.
> target = self.dbg.CreateTarget(exe)
> self.assertTrue(target, VALID_TARGET)
>
> try:
> list = target.FindFunctions('c', lldb.eFunctionNameTypeAuto)
> self.assertTrue(list.GetSize() == 1)
>
> for sc in list:
> try:
>
> self.assertTrue(sc.GetModule().GetFileSpec().GetFilename() == exe_name)
> self.assertTrue(sc.GetSymbol().GetName() == 'c')
> finally:
> del sc
>
> finally:
> del list
>
> The finally blocks ensure that the corresponding C++ objects are
> destroyed, even if the function exits as a result of a Python exception
> (e.g., if one of the assertion expressions is false and the code throws an
> exception).  Since the objects are destroyed, the reference counts are back
> to where they should be, and the orphaned module is closed when the target
> is deleted.
>
> But this is ugly and maintaining it would be error prone.  Is there a
> better way to address this?
>
> In general, it seems bad that our tests aren't well-isolated.  I
> sympathize with the concern that re-starting LLDB for each test case would
> slow down testing, but I'm also concerned that the state of LLDB for any
> given test case can depend on what happened in the earlier cases.
>
> Adrian.
>
> ___
> lldb-dev mailing list
> lldb-dev@lists.llvm.org
> http://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-dev
>
>


-- 
Oleksiy Vyalov | Software Engineer | ovya...@google.com
___
lldb-dev mailing list
lldb-dev@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-dev


Re: [lldb-dev] Question on assert

2015-10-15 Thread Todd Fiala via lldb-dev
This seems to be working.  I put it up for review here, Tamas:

http://reviews.llvm.org/D13777

On Thu, Oct 15, 2015 at 9:03 AM, Todd Fiala  wrote:

> I'm re-running the tests to make sure, but I think that fixed it.  I had
> always seen it at least once on test runs locally, but didn't see it on the
> last one.
>
> On Thu, Oct 15, 2015 at 8:10 AM, Todd Fiala  wrote:
>
>> Okay!  I'll give that a shot now and report back what I find.
>>
>> Thanks, Tamas :-)
>>
>> -Todd
>>
>> On Thu, Oct 15, 2015 at 3:37 AM, Tamas Berghammer > > wrote:
>>
>>> Hi Todd,
>>>
>>> The 64 bit ID of a DIE is built up in the following way:
>>> * The offset of the DIE is in the lower 32 bit
>>> * If we are using SymbolFileDWARF then the higher 32 bit is the offset
>>> of the compile unit this DIE belongs to
>>> * If we are using SymbolFileDWARFDwo then the higher 32 bit is the
>>> offset of the base compile unit in the parent SymbolFileDWARF
>>> * If we are using SymbolFileDWARFDebugMap then the higher 32 bit is the
>>> ID of the SymbolFileDWARF this DIE belongs to
>>> * If the higher 32 bit is 0 then that means that the source of the DIE
>>> isn't specified
>>>
>>> The assert then tries to verify that one of the following conditions
>>> holds:
>>> * The higher 32 bit of "id" is 0 what means that we don't have a symbol
>>> file pointer (AFAIK shouldn't happen) or we are coming from a
>>> SymbolFileDWARF
>>> * The higher 32 bit of "cu_id" is 0 what means that the compile unit is
>>> at 0 offset what is the case for the single compile units in
>>> SymbolFileDWARFDwo (and I think for SymbolFileDWARFDebugMap)
>>> * The higher 32 bit of "id" (what is the ID of the SymbolFileDWARF we
>>> are belonging to) matches with the higher 32 bit of "cu_id" (what is the
>>> offset of the compile unit in the base object file)
>>>
>>> After thinking a bit more about the assert I think the problem is that
>>> the way I calculate cu_id is incompatible for the case when we are using
>>> SymbolFileDWARFDebugMap.
>>>
>>> I think changing line 188 to the following should fix the issue:
>>> lldb::user_id_t cu_id = m_cu->GetID()&0xull;
>>>
>>> Please give it a try on OSX and let me know if it helps. I tested it on
>>> Linux and it isn't cause any regression there.
>>>
>>> Thanks,
>>> Tamas
>>>
>>> On Wed, Oct 14, 2015 at 9:13 PM Todd Fiala  wrote:
>>>
 Hi Tamas,

 There is an assert in DWARFDIE.cpp (lines 189 - 191) that we're hitting
 on the OS X side somewhat frequently nowadays:

 assert ((id&0xull) == 0 ||

 (cu_id&0xll) == 0 ||

 (id&0xull) == (cu_id&
 0xll));


 It does not seem to get hit consistently.  We're trying to tease apart
 what it is trying to do.  It's a bit strange since it is saying that the
 assert should not fire if any one of three clauses is true.  But it's hard
 to figure out what exactly is going on there.


 Can you elucidate what this is trying to do?  Thanks!

 --
 -Todd

>>>
>>
>>
>> --
>> -Todd
>>
>
>
>
> --
> -Todd
>



-- 
-Todd
___
lldb-dev mailing list
lldb-dev@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-dev


Re: [lldb-dev] Python object lifetimes affect the reliability of tests

2015-10-15 Thread Zachary Turner via lldb-dev
That wouldn't work in this case because it causes a failure from one test
to the next.  So a single test suite has 5 tests, and the second one fails
because the first one didn't clean up correctly.  You couldn't call
ScriptInterpreterpython::Clear here, because then you'd have to initialize
it again, and while it might work, it seems scary and like something which
is untested and we recommend you don't do.

What about calling `gc.collect()` in the tearDown() method?

On Thu, Oct 15, 2015 at 9:10 AM Oleksiy Vyalov via lldb-dev <
lldb-dev@lists.llvm.org> wrote:

> I stumbled upon similar problem when was looking into why SBDebugger
> wasn't unloaded upon app's exit.
> The problem was in Python global objects like lldb.debugger, lldb.target
> sitting around.
> So, my guess is to try to call ScriptInterpreterPython::Clear  within
> test's tearDown call - e.g., expose Clear method as part of
> SBCommandInterpreter and call it via SBDebugger::GetCommandInterpreter
>
> On Thu, Oct 15, 2015 at 8:50 AM, Adrian McCarthy via lldb-dev <
> lldb-dev@lists.llvm.org> wrote:
>
>> I've tracked down a source of flakiness in tests on Windows to Python
>> object lifetimes and the SB interface, and I'm wondering how best to handle
>> it.
>>
>> Consider this portion of a test from TestTargetAPI:
>>
>> def find_functions(self, exe_name):
>> """Exercise SBTaget.FindFunctions() API."""
>> exe = os.path.join(os.getcwd(), exe_name)
>>
>> # Create a target by the debugger.
>> target = self.dbg.CreateTarget(exe)
>> self.assertTrue(target, VALID_TARGET)
>> list = target.FindFunctions('c', lldb.eFunctionNameTypeAuto)
>> self.assertTrue(list.GetSize() == 1)
>>
>> for sc in list:
>> self.assertTrue(sc.GetModule().GetFileSpec().GetFilename() ==
>> exe_name)
>> self.assertTrue(sc.GetSymbol().GetName() == 'c')
>>
>> The local variables go out of scope when the function exits, but the SB
>> (C++) objects they represent aren't (always) immediately destroyed.  At
>> least some of these objects keep references to the executable module in the
>> shared module list, so when the test framework cleans up and calls
>> `SBDebugger::DeleteTarget`, the module isn't orphaned, so LLDB maintains an
>> open handle to the executable.
>>
>> The result of the lingering handle is that, when the next test case in
>> the test suite tries to re-build the executable, it fails because the file
>> is not writable.  (This is problematic on Windows because the file system
>> works differently in this regard than Unix derivatives.)  Every subsequent
>> case in the test suite fails.
>>
>> I managed to make the test work reliably by rewriting it like this:
>>
>> def find_functions(self, exe_name):
>> """Exercise SBTaget.FindFunctions() API."""
>> exe = os.path.join(os.getcwd(), exe_name)
>>
>> # Create a target by the debugger.
>> target = self.dbg.CreateTarget(exe)
>> self.assertTrue(target, VALID_TARGET)
>>
>> try:
>> list = target.FindFunctions('c', lldb.eFunctionNameTypeAuto)
>> self.assertTrue(list.GetSize() == 1)
>>
>> for sc in list:
>> try:
>>
>> self.assertTrue(sc.GetModule().GetFileSpec().GetFilename() == exe_name)
>> self.assertTrue(sc.GetSymbol().GetName() == 'c')
>> finally:
>> del sc
>>
>> finally:
>> del list
>>
>> The finally blocks ensure that the corresponding C++ objects are
>> destroyed, even if the function exits as a result of a Python exception
>> (e.g., if one of the assertion expressions is false and the code throws an
>> exception).  Since the objects are destroyed, the reference counts are back
>> to where they should be, and the orphaned module is closed when the target
>> is deleted.
>>
>> But this is ugly and maintaining it would be error prone.  Is there a
>> better way to address this?
>>
>> In general, it seems bad that our tests aren't well-isolated.  I
>> sympathize with the concern that re-starting LLDB for each test case would
>> slow down testing, but I'm also concerned that the state of LLDB for any
>> given test case can depend on what happened in the earlier cases.
>>
>> Adrian.
>>
>> ___
>> lldb-dev mailing list
>> lldb-dev@lists.llvm.org
>> http://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-dev
>>
>>
>
>
> --
> Oleksiy Vyalov | Software Engineer | ovya...@google.com
> ___
> lldb-dev mailing list
> lldb-dev@lists.llvm.org
> http://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-dev
>
___
lldb-dev mailing list
lldb-dev@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-dev


Re: [lldb-dev] Python object lifetimes affect the reliability of tests

2015-10-15 Thread Todd Fiala via lldb-dev
On Thu, Oct 15, 2015 at 8:50 AM, Adrian McCarthy via lldb-dev <
lldb-dev@lists.llvm.org> wrote:

> I've tracked down a source of flakiness in tests on Windows to Python
> object lifetimes and the SB interface, and I'm wondering how best to handle
> it.
>
> Consider this portion of a test from TestTargetAPI:
>
> def find_functions(self, exe_name):
> """Exercise SBTaget.FindFunctions() API."""
> exe = os.path.join(os.getcwd(), exe_name)
>
> # Create a target by the debugger.
> target = self.dbg.CreateTarget(exe)
> self.assertTrue(target, VALID_TARGET)
> list = target.FindFunctions('c', lldb.eFunctionNameTypeAuto)
> self.assertTrue(list.GetSize() == 1)
>
> for sc in list:
> self.assertTrue(sc.GetModule().GetFileSpec().GetFilename() ==
> exe_name)
> self.assertTrue(sc.GetSymbol().GetName() == 'c')
>
> The local variables go out of scope when the function exits, but the SB
> (C++) objects they represent aren't (always) immediately destroyed.  At
> least some of these objects keep references to the executable module in the
> shared module list, so when the test framework cleans up and calls
> `SBDebugger::DeleteTarget`, the module isn't orphaned, so LLDB maintains an
> open handle to the executable.
>
> The result of the lingering handle is that, when the next test case in the
> test suite tries to re-build the executable, it fails because the file is
> not writable.  (This is problematic on Windows because the file system
> works differently in this regard than Unix derivatives.)  Every subsequent
> case in the test suite fails.
>
> I managed to make the test work reliably by rewriting it like this:
>
> def find_functions(self, exe_name):
> """Exercise SBTaget.FindFunctions() API."""
> exe = os.path.join(os.getcwd(), exe_name)
>
> # Create a target by the debugger.
> target = self.dbg.CreateTarget(exe)
> self.assertTrue(target, VALID_TARGET)
>
> try:
> list = target.FindFunctions('c', lldb.eFunctionNameTypeAuto)
> self.assertTrue(list.GetSize() == 1)
>
> for sc in list:
> try:
>
> self.assertTrue(sc.GetModule().GetFileSpec().GetFilename() == exe_name)
> self.assertTrue(sc.GetSymbol().GetName() == 'c')
> finally:
> del sc
>
> finally:
> del list
>
> The finally blocks ensure that the corresponding C++ objects are
> destroyed, even if the function exits as a result of a Python exception
> (e.g., if one of the assertion expressions is false and the code throws an
> exception).  Since the objects are destroyed, the reference counts are back
> to where they should be, and the orphaned module is closed when the target
> is deleted.
>
> But this is ugly and maintaining it would be error prone.  Is there a
> better way to address this?
>
>
We should drill into why they're not cleaning up right away.  If it's out
of our control (i.e. some kind of lazy clean up), then maybe we can put in
some meta-magic that generates the deletes like you added.


> In general, it seems bad that our tests aren't well-isolated.
>

Each .py file is getting run as a separate process unless the tests are run
in a way that disables the concurrent test runner.  Methods within a given
.py file are getting run in the same process.  So we're really talking
about test methods within a file, not test methods across files.


> I sympathize with the concern that re-starting LLDB for each test case
> would slow down testing, but I'm also concerned that the state of LLDB for
> any given test case can depend on what happened in the earlier cases.
>
>
One thing I plan to do mid-term is:
* announce all the tests that can run in a python file
* ensure we report on tests *not* run because of a crash (i.e. get counts
for true unknowns, not just info on tests that pass/fail/error).
* having an "announce-only" pass so we can dynamically collect up all he
tests without necessarily running them.  (for things like test runners that
can list all the tests available and want to show progress).

This would conceivably support the underpinnings to say:
* collect all the tests (announce-only)
* add a way to fire up a single test method (we sortta have that already),
and only do one test method per process.

I think there is additional coordination that would have to happen to
handle inferior binaries build for a test and make sure they exist where
(and when) they need to, with the right arch settings and whatnot.

But, that would definitely get full isolation per test method.


> Adrian.
>
> ___
> lldb-dev mailing list
> lldb-dev@lists.llvm.org
> http://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-dev
>
>


-- 
-Todd
___
lldb-dev mailing list
lldb-dev@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/ll

Re: [lldb-dev] Python object lifetimes affect the reliability of tests

2015-10-15 Thread Todd Fiala via lldb-dev
On Thu, Oct 15, 2015 at 9:23 AM, Zachary Turner via lldb-dev <
lldb-dev@lists.llvm.org> wrote:

> That wouldn't work in this case because it causes a failure from one test
> to the next.  So a single test suite has 5 tests, and the second one fails
> because the first one didn't clean up correctly.  You couldn't call
> ScriptInterpreterpython::Clear here, because then you'd have to initialize
> it again, and while it might work, it seems scary and like something which
> is untested and we recommend you don't do.
>
> What about calling `gc.collect()` in the tearDown() method?
>

If it's a laziness thing, that seems like it might do it.  I would think we
could stick that in the base test class and get it everywhere.  Is that
something you can try, Adrian?


>
> On Thu, Oct 15, 2015 at 9:10 AM Oleksiy Vyalov via lldb-dev <
> lldb-dev@lists.llvm.org> wrote:
>
>> I stumbled upon similar problem when was looking into why SBDebugger
>> wasn't unloaded upon app's exit.
>> The problem was in Python global objects like lldb.debugger, lldb.target
>> sitting around.
>> So, my guess is to try to call ScriptInterpreterPython::Clear  within
>> test's tearDown call - e.g., expose Clear method as part of
>> SBCommandInterpreter and call it via SBDebugger::GetCommandInterpreter
>>
>> On Thu, Oct 15, 2015 at 8:50 AM, Adrian McCarthy via lldb-dev <
>> lldb-dev@lists.llvm.org> wrote:
>>
>>> I've tracked down a source of flakiness in tests on Windows to Python
>>> object lifetimes and the SB interface, and I'm wondering how best to handle
>>> it.
>>>
>>> Consider this portion of a test from TestTargetAPI:
>>>
>>> def find_functions(self, exe_name):
>>> """Exercise SBTaget.FindFunctions() API."""
>>> exe = os.path.join(os.getcwd(), exe_name)
>>>
>>> # Create a target by the debugger.
>>> target = self.dbg.CreateTarget(exe)
>>> self.assertTrue(target, VALID_TARGET)
>>> list = target.FindFunctions('c', lldb.eFunctionNameTypeAuto)
>>> self.assertTrue(list.GetSize() == 1)
>>>
>>> for sc in list:
>>> self.assertTrue(sc.GetModule().GetFileSpec().GetFilename()
>>> == exe_name)
>>> self.assertTrue(sc.GetSymbol().GetName() == 'c')
>>>
>>> The local variables go out of scope when the function exits, but the SB
>>> (C++) objects they represent aren't (always) immediately destroyed.  At
>>> least some of these objects keep references to the executable module in the
>>> shared module list, so when the test framework cleans up and calls
>>> `SBDebugger::DeleteTarget`, the module isn't orphaned, so LLDB maintains an
>>> open handle to the executable.
>>>
>>> The result of the lingering handle is that, when the next test case in
>>> the test suite tries to re-build the executable, it fails because the file
>>> is not writable.  (This is problematic on Windows because the file system
>>> works differently in this regard than Unix derivatives.)  Every subsequent
>>> case in the test suite fails.
>>>
>>> I managed to make the test work reliably by rewriting it like this:
>>>
>>> def find_functions(self, exe_name):
>>> """Exercise SBTaget.FindFunctions() API."""
>>> exe = os.path.join(os.getcwd(), exe_name)
>>>
>>> # Create a target by the debugger.
>>> target = self.dbg.CreateTarget(exe)
>>> self.assertTrue(target, VALID_TARGET)
>>>
>>> try:
>>> list = target.FindFunctions('c', lldb.eFunctionNameTypeAuto)
>>> self.assertTrue(list.GetSize() == 1)
>>>
>>> for sc in list:
>>> try:
>>>
>>> self.assertTrue(sc.GetModule().GetFileSpec().GetFilename() == exe_name)
>>> self.assertTrue(sc.GetSymbol().GetName() == 'c')
>>> finally:
>>> del sc
>>>
>>> finally:
>>> del list
>>>
>>> The finally blocks ensure that the corresponding C++ objects are
>>> destroyed, even if the function exits as a result of a Python exception
>>> (e.g., if one of the assertion expressions is false and the code throws an
>>> exception).  Since the objects are destroyed, the reference counts are back
>>> to where they should be, and the orphaned module is closed when the target
>>> is deleted.
>>>
>>> But this is ugly and maintaining it would be error prone.  Is there a
>>> better way to address this?
>>>
>>> In general, it seems bad that our tests aren't well-isolated.  I
>>> sympathize with the concern that re-starting LLDB for each test case would
>>> slow down testing, but I'm also concerned that the state of LLDB for any
>>> given test case can depend on what happened in the earlier cases.
>>>
>>> Adrian.
>>>
>>> ___
>>> lldb-dev mailing list
>>> lldb-dev@lists.llvm.org
>>> http://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-dev
>>>
>>>
>>
>>
>> --
>> Oleksiy Vyalov | Software Engineer | ovya...@google.com
>> ___
>> lldb-dev m

[lldb-dev] [Bug 25194] New: LLDB-Server Assertion raised when single stepping on MIPS

2015-10-15 Thread via lldb-dev
https://llvm.org/bugs/show_bug.cgi?id=25194

Bug ID: 25194
   Summary: LLDB-Server Assertion raised when single stepping on
MIPS
   Product: lldb
   Version: unspecified
  Hardware: PC
OS: Linux
Status: NEW
  Severity: normal
  Priority: P
 Component: All Bugs
  Assignee: lldb-dev@lists.llvm.org
  Reporter: ai...@codeplay.com
CC: llvm-b...@lists.llvm.org
Classification: Unclassified

When using LLDB-Server on the Android Mips32 emulator and assertion is raised
when performing a single step.  The sample program attached can be used to
reproduce this problem.

The sample program was compiled using the mips toolchain from the Android NDK,
specificaly: gcc version 4.9 20140827 (prerelease) (GCC).
The binary was compiled at -O0 with debug info.

The test case is as follows:


#include 
#include 

static volatile bool e = true;

int main() {

printf("hello world!\n");

while (e) {
usleep(1);
}

printf( "exiting...\n" );
return 0;
}


If I place a breakpoint on line 11 (usleep) and then inside of usleep for 10
instructions or so, the following occurs.

1|root@generic_mips:/data # ./lldb-server-3.8.0-s g *:1234 -- test 
using the default platform: host
Launched 'test' as process 963...
lldb-server-local_buildListening to port 1234 for a connection from *...
Connection established.
/home/aidan/rs/llvm/tools/lldb/source/Plugins/Process/Linux/NativeProcessLinux.cpp:1640:
lldb_private::Error
lldb_private::process_linux::NativeProcessLinux::SetupSoftwareSingleStepping(lldb_private::process_linux::NativeThreadLinux&):
assertion "pc_it != baton.m_register_values.end() && "Emulation was successfull
but PC wasn't updated"" failed
Aborted 

>From the perspective of lldb server I see this:

(lldb) s
Process 963 stopped
* thread #1: tid = 963, 0x77d35748, name = 'test', stop reason = instruction
step into
frame #0: 0x77d35748
->  0x77d35748: addiu  $sp, $sp, -40
0x77d3574c: addiu  $7, $6, 16960
0x77d35750: mfhi   $5
0x77d35754: sw $ra, 36($sp)
(lldb) s
Process 963 exited with status = -1 (0x) lost connection

I have seen the same assersion fire up when single stepping in a more
complicated scenario.

My version of LLDB was build from the upstream git mirror from commit:
adb9afc13ea113e2daeed6c739ecc2d52e2fd7d7

I have attached the source code for the sample, and a copy of my compiled
binary.

-- 
You are receiving this mail because:
You are the assignee for the bug.
___
lldb-dev mailing list
lldb-dev@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-dev


Re: [lldb-dev] Python object lifetimes affect the reliability of tests

2015-10-15 Thread Adrian McCarthy via lldb-dev
On Thu, Oct 15, 2015 at 9:31 AM, Todd Fiala  wrote:

>
>
> On Thu, Oct 15, 2015 at 9:23 AM, Zachary Turner via lldb-dev <
> lldb-dev@lists.llvm.org> wrote:
>
>> That wouldn't work in this case because it causes a failure from one test
>> to the next.  So a single test suite has 5 tests, and the second one fails
>> because the first one didn't clean up correctly.  You couldn't call
>> ScriptInterpreterpython::Clear here, because then you'd have to initialize
>> it again, and while it might work, it seems scary and like something which
>> is untested and we recommend you don't do.
>>
>> What about calling `gc.collect()` in the tearDown() method?
>>
>
> If it's a laziness thing, that seems like it might do it.  I would think
> we could stick that in the base test class and get it everywhere.  Is that
> something you can try, Adrian?
>

That seemed promising, but it doesn't seem to work, so maybe I don't
understand the problem as well as I thought I did.


>
>
>>
>> On Thu, Oct 15, 2015 at 9:10 AM Oleksiy Vyalov via lldb-dev <
>> lldb-dev@lists.llvm.org> wrote:
>>
>>> I stumbled upon similar problem when was looking into why SBDebugger
>>> wasn't unloaded upon app's exit.
>>> The problem was in Python global objects like lldb.debugger, lldb.target
>>> sitting around.
>>> So, my guess is to try to call ScriptInterpreterPython::Clear  within
>>> test's tearDown call - e.g., expose Clear method as part of
>>> SBCommandInterpreter and call it via SBDebugger::GetCommandInterpreter
>>>
>>> On Thu, Oct 15, 2015 at 8:50 AM, Adrian McCarthy via lldb-dev <
>>> lldb-dev@lists.llvm.org> wrote:
>>>
 I've tracked down a source of flakiness in tests on Windows to Python
 object lifetimes and the SB interface, and I'm wondering how best to handle
 it.

 Consider this portion of a test from TestTargetAPI:

 def find_functions(self, exe_name):
 """Exercise SBTaget.FindFunctions() API."""
 exe = os.path.join(os.getcwd(), exe_name)

 # Create a target by the debugger.
 target = self.dbg.CreateTarget(exe)
 self.assertTrue(target, VALID_TARGET)
 list = target.FindFunctions('c', lldb.eFunctionNameTypeAuto)
 self.assertTrue(list.GetSize() == 1)

 for sc in list:
 self.assertTrue(sc.GetModule().GetFileSpec().GetFilename()
 == exe_name)
 self.assertTrue(sc.GetSymbol().GetName() == 'c')

 The local variables go out of scope when the function exits, but the SB
 (C++) objects they represent aren't (always) immediately destroyed.  At
 least some of these objects keep references to the executable module in the
 shared module list, so when the test framework cleans up and calls
 `SBDebugger::DeleteTarget`, the module isn't orphaned, so LLDB maintains an
 open handle to the executable.

 The result of the lingering handle is that, when the next test case in
 the test suite tries to re-build the executable, it fails because the file
 is not writable.  (This is problematic on Windows because the file system
 works differently in this regard than Unix derivatives.)  Every subsequent
 case in the test suite fails.

 I managed to make the test work reliably by rewriting it like this:

 def find_functions(self, exe_name):
 """Exercise SBTaget.FindFunctions() API."""
 exe = os.path.join(os.getcwd(), exe_name)

 # Create a target by the debugger.
 target = self.dbg.CreateTarget(exe)
 self.assertTrue(target, VALID_TARGET)

 try:
 list = target.FindFunctions('c', lldb.eFunctionNameTypeAuto)
 self.assertTrue(list.GetSize() == 1)

 for sc in list:
 try:

 self.assertTrue(sc.GetModule().GetFileSpec().GetFilename() == exe_name)
 self.assertTrue(sc.GetSymbol().GetName() == 'c')
 finally:
 del sc

 finally:
 del list

 The finally blocks ensure that the corresponding C++ objects are
 destroyed, even if the function exits as a result of a Python exception
 (e.g., if one of the assertion expressions is false and the code throws an
 exception).  Since the objects are destroyed, the reference counts are back
 to where they should be, and the orphaned module is closed when the target
 is deleted.

 But this is ugly and maintaining it would be error prone.  Is there a
 better way to address this?

 In general, it seems bad that our tests aren't well-isolated.  I
 sympathize with the concern that re-starting LLDB for each test case would
 slow down testing, but I'm also concerned that the state of LLDB for any
 given test case can depend on what happened in the earlier cases.

 Adrian.

 

Re: [lldb-dev] Python object lifetimes affect the reliability of tests

2015-10-15 Thread Adrian McCarthy via lldb-dev
The gc.collect works only if I set the variables to None in the finally
blocks, which is no better than just del'ing the objects in the finally
blocks.

On Thu, Oct 15, 2015 at 9:47 AM, Adrian McCarthy 
wrote:

>
> On Thu, Oct 15, 2015 at 9:31 AM, Todd Fiala  wrote:
>
>>
>>
>> On Thu, Oct 15, 2015 at 9:23 AM, Zachary Turner via lldb-dev <
>> lldb-dev@lists.llvm.org> wrote:
>>
>>> That wouldn't work in this case because it causes a failure from one
>>> test to the next.  So a single test suite has 5 tests, and the second one
>>> fails because the first one didn't clean up correctly.  You couldn't call
>>> ScriptInterpreterpython::Clear here, because then you'd have to initialize
>>> it again, and while it might work, it seems scary and like something which
>>> is untested and we recommend you don't do.
>>>
>>> What about calling `gc.collect()` in the tearDown() method?
>>>
>>
>> If it's a laziness thing, that seems like it might do it.  I would think
>> we could stick that in the base test class and get it everywhere.  Is that
>> something you can try, Adrian?
>>
>
> That seemed promising, but it doesn't seem to work, so maybe I don't
> understand the problem as well as I thought I did.
>
>
>>
>>
>>>
>>> On Thu, Oct 15, 2015 at 9:10 AM Oleksiy Vyalov via lldb-dev <
>>> lldb-dev@lists.llvm.org> wrote:
>>>
 I stumbled upon similar problem when was looking into why SBDebugger
 wasn't unloaded upon app's exit.
 The problem was in Python global objects like lldb.debugger,
 lldb.target sitting around.
 So, my guess is to try to call ScriptInterpreterPython::Clear  within
 test's tearDown call - e.g., expose Clear method as part of
 SBCommandInterpreter and call it via SBDebugger::GetCommandInterpreter

 On Thu, Oct 15, 2015 at 8:50 AM, Adrian McCarthy via lldb-dev <
 lldb-dev@lists.llvm.org> wrote:

> I've tracked down a source of flakiness in tests on Windows to Python
> object lifetimes and the SB interface, and I'm wondering how best to 
> handle
> it.
>
> Consider this portion of a test from TestTargetAPI:
>
> def find_functions(self, exe_name):
> """Exercise SBTaget.FindFunctions() API."""
> exe = os.path.join(os.getcwd(), exe_name)
>
> # Create a target by the debugger.
> target = self.dbg.CreateTarget(exe)
> self.assertTrue(target, VALID_TARGET)
> list = target.FindFunctions('c', lldb.eFunctionNameTypeAuto)
> self.assertTrue(list.GetSize() == 1)
>
> for sc in list:
> self.assertTrue(sc.GetModule().GetFileSpec().GetFilename()
> == exe_name)
> self.assertTrue(sc.GetSymbol().GetName() == 'c')
>
> The local variables go out of scope when the function exits, but the
> SB (C++) objects they represent aren't (always) immediately destroyed.  At
> least some of these objects keep references to the executable module in 
> the
> shared module list, so when the test framework cleans up and calls
> `SBDebugger::DeleteTarget`, the module isn't orphaned, so LLDB maintains 
> an
> open handle to the executable.
>
> The result of the lingering handle is that, when the next test case in
> the test suite tries to re-build the executable, it fails because the file
> is not writable.  (This is problematic on Windows because the file system
> works differently in this regard than Unix derivatives.)  Every subsequent
> case in the test suite fails.
>
> I managed to make the test work reliably by rewriting it like this:
>
> def find_functions(self, exe_name):
> """Exercise SBTaget.FindFunctions() API."""
> exe = os.path.join(os.getcwd(), exe_name)
>
> # Create a target by the debugger.
> target = self.dbg.CreateTarget(exe)
> self.assertTrue(target, VALID_TARGET)
>
> try:
> list = target.FindFunctions('c',
> lldb.eFunctionNameTypeAuto)
> self.assertTrue(list.GetSize() == 1)
>
> for sc in list:
> try:
>
> self.assertTrue(sc.GetModule().GetFileSpec().GetFilename() == exe_name)
> self.assertTrue(sc.GetSymbol().GetName() == 'c')
> finally:
> del sc
>
> finally:
> del list
>
> The finally blocks ensure that the corresponding C++ objects are
> destroyed, even if the function exits as a result of a Python exception
> (e.g., if one of the assertion expressions is false and the code throws an
> exception).  Since the objects are destroyed, the reference counts are 
> back
> to where they should be, and the orphaned module is closed when the target
> is deleted.
>
> But this is ugly and maintaining it would be error prone.  Is there a
> better 

Re: [lldb-dev] Python object lifetimes affect the reliability of tests

2015-10-15 Thread Greg Clayton via lldb-dev

> On Oct 15, 2015, at 8:50 AM, Adrian McCarthy via lldb-dev 
>  wrote:
> 
> I've tracked down a source of flakiness in tests on Windows to Python object 
> lifetimes and the SB interface, and I'm wondering how best to handle it.
> 
> Consider this portion of a test from TestTargetAPI:
> 
>  def find_functions(self, exe_name):
>  """Exercise SBTaget.FindFunctions() API."""
>  exe = os.path.join(os.getcwd(), exe_name)
> 
>  # Create a target by the debugger.
>  target = self.dbg.CreateTarget(exe)
>  self.assertTrue(target, VALID_TARGET)
>  list = target.FindFunctions('c', lldb.eFunctionNameTypeAuto)
>  self.assertTrue(list.GetSize() == 1)
> 
>  for sc in list:
>  self.assertTrue(sc.GetModule().GetFileSpec().GetFilename() == 
> exe_name)
>  self.assertTrue(sc.GetSymbol().GetName() == 'c')
> 
> The local variables go out of scope when the function exits, but the SB (C++) 
> objects they represent aren't (always) immediately destroyed.  At least some 
> of these objects keep references to the executable module in the shared 
> module list, so when the test framework cleans up and calls 
> `SBDebugger::DeleteTarget`, the module isn't orphaned, so LLDB maintains an 
> open handle to the executable.

Creating a target with:

target = self.dbg.CreateTarget(exe)

Will give you a SBTarget object that has a strong reference to the target, but 
the debugger still has a copy in its target list, so the SBTarget isn't 
designed to delete the object when the target variable goes out of scope. If 
you want the target to be deleted, you actually have to call through to the 
debugger with:


 bool
 SBDebugger:DeleteTarget (lldb::SBTarget &target);


So the right way to clean up the target is:

 self.dbg.DeleteTarget(target);

Even though there might be code within LLDB that has a valid shared pointer to 
the lldb_private::Target still, it calls lldb_private::Target::Destroy() which 
clears out most instance variable (the module list, the process, any plug-ins, 
etc).

SBTarget objects have strong references so that they _can_ keep the object 
alive if needed in case someone else destroys the target on another thread, but 
they don't control the lifetime of the target.

Other objects have weak references to the objects: SBProcess, SBThread, 
SBFrame. If the objects are actually destroyed already, the weak pointer won't 
be able to get a valid shared pointer to the underlying object
and any SB API calls on these objects will return error, none, zero, etc...

> 
> The result of the lingering handle is that, when the next test case in the 
> test suite tries to re-build the executable, it fails because the file is not 
> writable.  (This is problematic on Windows because the file system works 
> differently in this regard than Unix derivatives.)  Every subsequent case in 
> the test suite fails.
> 
> I managed to make the test work reliably by rewriting it like this:
> 
>  def find_functions(self, exe_name):
>  """Exercise SBTaget.FindFunctions() API."""
>  exe = os.path.join(os.getcwd(), exe_name)
> 
>  # Create a target by the debugger.
>  target = self.dbg.CreateTarget(exe)
>  self.assertTrue(target, VALID_TARGET)
> 
>  try:
>  list = target.FindFunctions('c', lldb.eFunctionNameTypeAuto)
>  self.assertTrue(list.GetSize() == 1)
> 
>  for sc in list:
>  try:
>  self.assertTrue(sc.GetModule().GetFileSpec().GetFilename() 
> == exe_name)
>  self.assertTrue(sc.GetSymbol().GetName() == 'c')
>  finally:
>  del sc
> 
>  finally:
>  del list
> 
> The finally blocks ensure that the corresponding C++ objects are destroyed, 
> even if the function exits as a result of a Python exception (e.g., if one of 
> the assertion expressions is false and the code throws an exception).  Since 
> the objects are destroyed, the reference counts are back to where they should 
> be, and the orphaned module is closed when the target is deleted.
> 
> But this is ugly and maintaining it would be error prone.  Is there a better 
> way to address this?

So you should be able to fix this by deleting the target with 
"self.dbg.DeleteTarget(target)"

We could change all tests over to always store any targets they create in the 
test object itself:

self.target = self.dbg.CreateTarget(exe)

Then the test suite could check for the existance of "self.target" and if it 
exists, it could call "self.dbg.DeleteTarget(self.target)" automatically to 
avoid such issues?



___
lldb-dev mailing list
lldb-dev@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-dev


Re: [lldb-dev] Python object lifetimes affect the reliability of tests

2015-10-15 Thread Zachary Turner via lldb-dev
We actually do already to the self.dbg.DeleteTarget(target), and that's the
line that's failing.  The reason it's failing is because the 'sc' reference
is still alive, which is holding an mmap, which causes a mandatory file
lock on Windows.

The diagnostics went pretty deep into python internals, but I think we
might have figured it out.  I don't know if this is a bug in Python, but I
think we'd probably need to ask Guido to be sure :)

As far as we can tell, what happens is that on the exceptional codepath
(e.g the assert fails), you walk back up the stack until you get to the
except handler.  This exception handler is in TestCase.run().  After it
handles the exception it goes and runs teardown.  However, for some reason,
Python is still holding a strong reference to the *traceback*, even though
we're completely out of the finally block.  What this means is that if you
call `sys.exc_info()` *even after you've exited the finally block, it still
returns info about the previous exception that's not even being handled
anymore.  I would have expected this to be gone since there's no exception
in-fligth anymore.  So basically, Python is still holding a reference to
the active exception, the exception holds the stack frame, the stack frame
holds the test method, the test method has locals, one of which is a
SymbolList, a member of which is symbol context, which has the file locked.

Our best guess is that if you have something like this:

def foo():
try:
   # Do stuff
except Exception, e:
   pass
# Do more stuff

that if the exceptional path is executed, then both e and sys.exc_info()
are alive *while* do more stuff is happening.  We've found two ways to
fixthis:

1) Change to this:
def foo():
try:
   # Do stuff
except Exception, e:
   pass
del e
sys.exc_clear()
# Do more stuff

2) Put the try / except inside a function.  When the function returns,
sys.exc_info() is cleared.

I like 2 better, but we're still testing some more to make sure this really
fixes it 100% of the time.

On Thu, Oct 15, 2015 at 10:25 AM Greg Clayton via lldb-dev <
lldb-dev@lists.llvm.org> wrote:

>
> > On Oct 15, 2015, at 8:50 AM, Adrian McCarthy via lldb-dev <
> lldb-dev@lists.llvm.org> wrote:
> >
> > I've tracked down a source of flakiness in tests on Windows to Python
> object lifetimes and the SB interface, and I'm wondering how best to handle
> it.
> >
> > Consider this portion of a test from TestTargetAPI:
> >
> >  def find_functions(self, exe_name):
> >  """Exercise SBTaget.FindFunctions() API."""
> >  exe = os.path.join(os.getcwd(), exe_name)
> >
> >  # Create a target by the debugger.
> >  target = self.dbg.CreateTarget(exe)
> >  self.assertTrue(target, VALID_TARGET)
> >  list = target.FindFunctions('c', lldb.eFunctionNameTypeAuto)
> >  self.assertTrue(list.GetSize() == 1)
> >
> >  for sc in list:
> >  self.assertTrue(sc.GetModule().GetFileSpec().GetFilename() ==
> exe_name)
> >  self.assertTrue(sc.GetSymbol().GetName() == 'c')
> >
> > The local variables go out of scope when the function exits, but the SB
> (C++) objects they represent aren't (always) immediately destroyed.  At
> least some of these objects keep references to the executable module in the
> shared module list, so when the test framework cleans up and calls
> `SBDebugger::DeleteTarget`, the module isn't orphaned, so LLDB maintains an
> open handle to the executable.
>
> Creating a target with:
>
> target = self.dbg.CreateTarget(exe)
>
> Will give you a SBTarget object that has a strong reference to the target,
> but the debugger still has a copy in its target list, so the SBTarget isn't
> designed to delete the object when the target variable goes out of scope.
> If you want the target to be deleted, you actually have to call through to
> the debugger with:
>
>
>  bool
>  SBDebugger:DeleteTarget (lldb::SBTarget &target);
>
>
> So the right way to clean up the target is:
>
>  self.dbg.DeleteTarget(target);
>
> Even though there might be code within LLDB that has a valid shared
> pointer to the lldb_private::Target still, it calls
> lldb_private::Target::Destroy() which clears out most instance variable
> (the module list, the process, any plug-ins, etc).
>
> SBTarget objects have strong references so that they _can_ keep the object
> alive if needed in case someone else destroys the target on another thread,
> but they don't control the lifetime of the target.
>
> Other objects have weak references to the objects: SBProcess, SBThread,
> SBFrame. If the objects are actually destroyed already, the weak pointer
> won't be able to get a valid shared pointer to the underlying object
> and any SB API calls on these objects will return error, none, zero, etc...
>
> >
> > The result of the lingering handle is that, when the next test case in
> the test suite tries to re-build the executable, it fails because the file
> is not writable.  (This is problematic on Windows be

Re: [lldb-dev] Python object lifetimes affect the reliability of tests

2015-10-15 Thread Zachary Turner via lldb-dev
To add more evidence for this, here's a small repro:

import sys

print "sys.exc_info() = ", "Empty" if sys.exc_info() == (None, None, None)
else "Valid"
try:
raise Exception
except Exception, e:
print "sys.exc_info() = ", "Empty" if sys.exc_info() == (None, None,
None) else "Valid"
pass

print "sys.exc_info() = ", "Empty" if sys.exc_info() == (None, None, None)
else "Valid"
print "e = ", "Bound" if 'e' in vars() else "Unbound"
pass

For me this prints
sys.exc_info() =  Empty
sys.exc_info() =  Valid
sys.exc_info() =  Valid
e =  Bound

On Thu, Oct 15, 2015 at 11:21 AM Zachary Turner  wrote:

> We actually do already to the self.dbg.DeleteTarget(target), and that's
> the line that's failing.  The reason it's failing is because the 'sc'
> reference is still alive, which is holding an mmap, which causes a
> mandatory file lock on Windows.
>
> The diagnostics went pretty deep into python internals, but I think we
> might have figured it out.  I don't know if this is a bug in Python, but I
> think we'd probably need to ask Guido to be sure :)
>
> As far as we can tell, what happens is that on the exceptional codepath
> (e.g the assert fails), you walk back up the stack until you get to the
> except handler.  This exception handler is in TestCase.run().  After it
> handles the exception it goes and runs teardown.  However, for some reason,
> Python is still holding a strong reference to the *traceback*, even though
> we're completely out of the finally block.  What this means is that if you
> call `sys.exc_info()` *even after you've exited the finally block, it still
> returns info about the previous exception that's not even being handled
> anymore.  I would have expected this to be gone since there's no exception
> in-fligth anymore.  So basically, Python is still holding a reference to
> the active exception, the exception holds the stack frame, the stack frame
> holds the test method, the test method has locals, one of which is a
> SymbolList, a member of which is symbol context, which has the file locked.
>
> Our best guess is that if you have something like this:
>
> def foo():
> try:
># Do stuff
> except Exception, e:
>pass
> # Do more stuff
>
> that if the exceptional path is executed, then both e and sys.exc_info()
> are alive *while* do more stuff is happening.  We've found two ways to
> fixthis:
>
> 1) Change to this:
> def foo():
> try:
># Do stuff
> except Exception, e:
>pass
> del e
> sys.exc_clear()
> # Do more stuff
>
> 2) Put the try / except inside a function.  When the function returns,
> sys.exc_info() is cleared.
>
> I like 2 better, but we're still testing some more to make sure this
> really fixes it 100% of the time.
>
> On Thu, Oct 15, 2015 at 10:25 AM Greg Clayton via lldb-dev <
> lldb-dev@lists.llvm.org> wrote:
>
>>
>> > On Oct 15, 2015, at 8:50 AM, Adrian McCarthy via lldb-dev <
>> lldb-dev@lists.llvm.org> wrote:
>> >
>> > I've tracked down a source of flakiness in tests on Windows to Python
>> object lifetimes and the SB interface, and I'm wondering how best to handle
>> it.
>> >
>> > Consider this portion of a test from TestTargetAPI:
>> >
>> >  def find_functions(self, exe_name):
>> >  """Exercise SBTaget.FindFunctions() API."""
>> >  exe = os.path.join(os.getcwd(), exe_name)
>> >
>> >  # Create a target by the debugger.
>> >  target = self.dbg.CreateTarget(exe)
>> >  self.assertTrue(target, VALID_TARGET)
>> >  list = target.FindFunctions('c', lldb.eFunctionNameTypeAuto)
>> >  self.assertTrue(list.GetSize() == 1)
>> >
>> >  for sc in list:
>> >  self.assertTrue(sc.GetModule().GetFileSpec().GetFilename() ==
>> exe_name)
>> >  self.assertTrue(sc.GetSymbol().GetName() == 'c')
>> >
>> > The local variables go out of scope when the function exits, but the SB
>> (C++) objects they represent aren't (always) immediately destroyed.  At
>> least some of these objects keep references to the executable module in the
>> shared module list, so when the test framework cleans up and calls
>> `SBDebugger::DeleteTarget`, the module isn't orphaned, so LLDB maintains an
>> open handle to the executable.
>>
>> Creating a target with:
>>
>> target = self.dbg.CreateTarget(exe)
>>
>> Will give you a SBTarget object that has a strong reference to the
>> target, but the debugger still has a copy in its target list, so the
>> SBTarget isn't designed to delete the object when the target variable goes
>> out of scope. If you want the target to be deleted, you actually have to
>> call through to the debugger with:
>>
>>
>>  bool
>>  SBDebugger:DeleteTarget (lldb::SBTarget &target);
>>
>>
>> So the right way to clean up the target is:
>>
>>  self.dbg.DeleteTarget(target);
>>
>> Even though there might be code within LLDB that has a valid shared
>> pointer to the lldb_private::Target still, it calls
>> lldb_private::Target::Destroy() which clears out most instance variable
>> (the mod

Re: [lldb-dev] Python object lifetimes affect the reliability of tests

2015-10-15 Thread Ryan Brown via lldb-dev
Couldn't we just change DeleteTarget to make sure everything is unmapped?

On Thu, Oct 15, 2015 at 11:34 AM Zachary Turner via lldb-dev <
lldb-dev@lists.llvm.org> wrote:

> To add more evidence for this, here's a small repro:
>
> import sys
>
> print "sys.exc_info() = ", "Empty" if sys.exc_info() == (None, None, None)
> else "Valid"
> try:
> raise Exception
> except Exception, e:
> print "sys.exc_info() = ", "Empty" if sys.exc_info() == (None, None,
> None) else "Valid"
> pass
>
> print "sys.exc_info() = ", "Empty" if sys.exc_info() == (None, None, None)
> else "Valid"
> print "e = ", "Bound" if 'e' in vars() else "Unbound"
> pass
>
> For me this prints
> sys.exc_info() =  Empty
> sys.exc_info() =  Valid
> sys.exc_info() =  Valid
> e =  Bound
>
> On Thu, Oct 15, 2015 at 11:21 AM Zachary Turner 
> wrote:
>
>> We actually do already to the self.dbg.DeleteTarget(target), and that's
>> the line that's failing.  The reason it's failing is because the 'sc'
>> reference is still alive, which is holding an mmap, which causes a
>> mandatory file lock on Windows.
>>
>> The diagnostics went pretty deep into python internals, but I think we
>> might have figured it out.  I don't know if this is a bug in Python, but I
>> think we'd probably need to ask Guido to be sure :)
>>
>> As far as we can tell, what happens is that on the exceptional codepath
>> (e.g the assert fails), you walk back up the stack until you get to the
>> except handler.  This exception handler is in TestCase.run().  After it
>> handles the exception it goes and runs teardown.  However, for some reason,
>> Python is still holding a strong reference to the *traceback*, even though
>> we're completely out of the finally block.  What this means is that if you
>> call `sys.exc_info()` *even after you've exited the finally block, it still
>> returns info about the previous exception that's not even being handled
>> anymore.  I would have expected this to be gone since there's no exception
>> in-fligth anymore.  So basically, Python is still holding a reference to
>> the active exception, the exception holds the stack frame, the stack frame
>> holds the test method, the test method has locals, one of which is a
>> SymbolList, a member of which is symbol context, which has the file locked.
>>
>> Our best guess is that if you have something like this:
>>
>> def foo():
>> try:
>># Do stuff
>> except Exception, e:
>>pass
>> # Do more stuff
>>
>> that if the exceptional path is executed, then both e and sys.exc_info()
>> are alive *while* do more stuff is happening.  We've found two ways to
>> fixthis:
>>
>> 1) Change to this:
>> def foo():
>> try:
>># Do stuff
>> except Exception, e:
>>pass
>> del e
>> sys.exc_clear()
>> # Do more stuff
>>
>> 2) Put the try / except inside a function.  When the function returns,
>> sys.exc_info() is cleared.
>>
>> I like 2 better, but we're still testing some more to make sure this
>> really fixes it 100% of the time.
>>
>> On Thu, Oct 15, 2015 at 10:25 AM Greg Clayton via lldb-dev <
>> lldb-dev@lists.llvm.org> wrote:
>>
>>>
>>> > On Oct 15, 2015, at 8:50 AM, Adrian McCarthy via lldb-dev <
>>> lldb-dev@lists.llvm.org> wrote:
>>> >
>>> > I've tracked down a source of flakiness in tests on Windows to Python
>>> object lifetimes and the SB interface, and I'm wondering how best to handle
>>> it.
>>> >
>>> > Consider this portion of a test from TestTargetAPI:
>>> >
>>> >  def find_functions(self, exe_name):
>>> >  """Exercise SBTaget.FindFunctions() API."""
>>> >  exe = os.path.join(os.getcwd(), exe_name)
>>> >
>>> >  # Create a target by the debugger.
>>> >  target = self.dbg.CreateTarget(exe)
>>> >  self.assertTrue(target, VALID_TARGET)
>>> >  list = target.FindFunctions('c', lldb.eFunctionNameTypeAuto)
>>> >  self.assertTrue(list.GetSize() == 1)
>>> >
>>> >  for sc in list:
>>> >  self.assertTrue(sc.GetModule().GetFileSpec().GetFilename() ==
>>> exe_name)
>>> >  self.assertTrue(sc.GetSymbol().GetName() == 'c')
>>> >
>>> > The local variables go out of scope when the function exits, but the
>>> SB (C++) objects they represent aren't (always) immediately destroyed.  At
>>> least some of these objects keep references to the executable module in the
>>> shared module list, so when the test framework cleans up and calls
>>> `SBDebugger::DeleteTarget`, the module isn't orphaned, so LLDB maintains an
>>> open handle to the executable.
>>>
>>> Creating a target with:
>>>
>>> target = self.dbg.CreateTarget(exe)
>>>
>>> Will give you a SBTarget object that has a strong reference to the
>>> target, but the debugger still has a copy in its target list, so the
>>> SBTarget isn't designed to delete the object when the target variable goes
>>> out of scope. If you want the target to be deleted, you actually have to
>>> call through to the debugger with:
>>>
>>>
>>>  bool
>>>  SBDebugger:DeleteTarget (lldb::SBTarg

Re: [lldb-dev] Python object lifetimes affect the reliability of tests

2015-10-15 Thread Zachary Turner via lldb-dev
It's not that simple.  A test method could be holding onto arbitrary
resources which could in theory prevent cleanup.  tests can register their
own cleanup handlers for example, and the teardown will call back into the
cleanup handler.  So one of those handlers could be making the assumption
that it can clean something up even though it can't because the test method
is still holding onto some resources.

I want to find out if this is a bug in my Python implementation, because it
seems quite strange to me that sys.exc_info(), which is documented to
return information about the exception *currently being processed*, still
returns something after it is finished being processed.

On Thu, Oct 15, 2015 at 11:36 AM Ryan Brown  wrote:

> Couldn't we just change DeleteTarget to make sure everything is unmapped?
>
> On Thu, Oct 15, 2015 at 11:34 AM Zachary Turner via lldb-dev <
> lldb-dev@lists.llvm.org> wrote:
>
>> To add more evidence for this, here's a small repro:
>>
>> import sys
>>
>> print "sys.exc_info() = ", "Empty" if sys.exc_info() == (None, None,
>> None) else "Valid"
>> try:
>> raise Exception
>> except Exception, e:
>> print "sys.exc_info() = ", "Empty" if sys.exc_info() == (None, None,
>> None) else "Valid"
>> pass
>>
>> print "sys.exc_info() = ", "Empty" if sys.exc_info() == (None, None,
>> None) else "Valid"
>> print "e = ", "Bound" if 'e' in vars() else "Unbound"
>> pass
>>
>> For me this prints
>> sys.exc_info() =  Empty
>> sys.exc_info() =  Valid
>> sys.exc_info() =  Valid
>> e =  Bound
>>
>> On Thu, Oct 15, 2015 at 11:21 AM Zachary Turner 
>> wrote:
>>
>>> We actually do already to the self.dbg.DeleteTarget(target), and that's
>>> the line that's failing.  The reason it's failing is because the 'sc'
>>> reference is still alive, which is holding an mmap, which causes a
>>> mandatory file lock on Windows.
>>>
>>> The diagnostics went pretty deep into python internals, but I think we
>>> might have figured it out.  I don't know if this is a bug in Python, but I
>>> think we'd probably need to ask Guido to be sure :)
>>>
>>> As far as we can tell, what happens is that on the exceptional codepath
>>> (e.g the assert fails), you walk back up the stack until you get to the
>>> except handler.  This exception handler is in TestCase.run().  After it
>>> handles the exception it goes and runs teardown.  However, for some reason,
>>> Python is still holding a strong reference to the *traceback*, even though
>>> we're completely out of the finally block.  What this means is that if you
>>> call `sys.exc_info()` *even after you've exited the finally block, it still
>>> returns info about the previous exception that's not even being handled
>>> anymore.  I would have expected this to be gone since there's no exception
>>> in-fligth anymore.  So basically, Python is still holding a reference to
>>> the active exception, the exception holds the stack frame, the stack frame
>>> holds the test method, the test method has locals, one of which is a
>>> SymbolList, a member of which is symbol context, which has the file locked.
>>>
>>> Our best guess is that if you have something like this:
>>>
>>> def foo():
>>> try:
>>># Do stuff
>>> except Exception, e:
>>>pass
>>> # Do more stuff
>>>
>>> that if the exceptional path is executed, then both e and sys.exc_info()
>>> are alive *while* do more stuff is happening.  We've found two ways to
>>> fixthis:
>>>
>>> 1) Change to this:
>>> def foo():
>>> try:
>>># Do stuff
>>> except Exception, e:
>>>pass
>>> del e
>>> sys.exc_clear()
>>> # Do more stuff
>>>
>>> 2) Put the try / except inside a function.  When the function returns,
>>> sys.exc_info() is cleared.
>>>
>>> I like 2 better, but we're still testing some more to make sure this
>>> really fixes it 100% of the time.
>>>
>>> On Thu, Oct 15, 2015 at 10:25 AM Greg Clayton via lldb-dev <
>>> lldb-dev@lists.llvm.org> wrote:
>>>

 > On Oct 15, 2015, at 8:50 AM, Adrian McCarthy via lldb-dev <
 lldb-dev@lists.llvm.org> wrote:
 >
 > I've tracked down a source of flakiness in tests on Windows to Python
 object lifetimes and the SB interface, and I'm wondering how best to handle
 it.
 >
 > Consider this portion of a test from TestTargetAPI:
 >
 >  def find_functions(self, exe_name):
 >  """Exercise SBTaget.FindFunctions() API."""
 >  exe = os.path.join(os.getcwd(), exe_name)
 >
 >  # Create a target by the debugger.
 >  target = self.dbg.CreateTarget(exe)
 >  self.assertTrue(target, VALID_TARGET)
 >  list = target.FindFunctions('c', lldb.eFunctionNameTypeAuto)
 >  self.assertTrue(list.GetSize() == 1)
 >
 >  for sc in list:
 >  self.assertTrue(sc.GetModule().GetFileSpec().GetFilename()
 == exe_name)
 >  self.assertTrue(sc.GetSymbol().GetName() == 'c')
 >
 > The local variables go out of scope when the fu

Re: [lldb-dev] Python object lifetimes affect the reliability of tests

2015-10-15 Thread Nico Weber via lldb-dev
One possible approach is to never run a built executable directly, but to
copy it to some other place (e.g. my-exe.exe -> my-exe-run-13.exe) and only
run the copied executable. Then rebuilding the original won't fail.

On Thu, Oct 15, 2015 at 9:10 AM, Oleksiy Vyalov via lldb-dev <
lldb-dev@lists.llvm.org> wrote:

> I stumbled upon similar problem when was looking into why SBDebugger
> wasn't unloaded upon app's exit.
> The problem was in Python global objects like lldb.debugger, lldb.target
> sitting around.
> So, my guess is to try to call ScriptInterpreterPython::Clear  within
> test's tearDown call - e.g., expose Clear method as part of
> SBCommandInterpreter and call it via SBDebugger::GetCommandInterpreter
>
> On Thu, Oct 15, 2015 at 8:50 AM, Adrian McCarthy via lldb-dev <
> lldb-dev@lists.llvm.org> wrote:
>
>> I've tracked down a source of flakiness in tests on Windows to Python
>> object lifetimes and the SB interface, and I'm wondering how best to handle
>> it.
>>
>> Consider this portion of a test from TestTargetAPI:
>>
>> def find_functions(self, exe_name):
>> """Exercise SBTaget.FindFunctions() API."""
>> exe = os.path.join(os.getcwd(), exe_name)
>>
>> # Create a target by the debugger.
>> target = self.dbg.CreateTarget(exe)
>> self.assertTrue(target, VALID_TARGET)
>> list = target.FindFunctions('c', lldb.eFunctionNameTypeAuto)
>> self.assertTrue(list.GetSize() == 1)
>>
>> for sc in list:
>> self.assertTrue(sc.GetModule().GetFileSpec().GetFilename() ==
>> exe_name)
>> self.assertTrue(sc.GetSymbol().GetName() == 'c')
>>
>> The local variables go out of scope when the function exits, but the SB
>> (C++) objects they represent aren't (always) immediately destroyed.  At
>> least some of these objects keep references to the executable module in the
>> shared module list, so when the test framework cleans up and calls
>> `SBDebugger::DeleteTarget`, the module isn't orphaned, so LLDB maintains an
>> open handle to the executable.
>>
>> The result of the lingering handle is that, when the next test case in
>> the test suite tries to re-build the executable, it fails because the file
>> is not writable.  (This is problematic on Windows because the file system
>> works differently in this regard than Unix derivatives.)  Every subsequent
>> case in the test suite fails.
>>
>> I managed to make the test work reliably by rewriting it like this:
>>
>> def find_functions(self, exe_name):
>> """Exercise SBTaget.FindFunctions() API."""
>> exe = os.path.join(os.getcwd(), exe_name)
>>
>> # Create a target by the debugger.
>> target = self.dbg.CreateTarget(exe)
>> self.assertTrue(target, VALID_TARGET)
>>
>> try:
>> list = target.FindFunctions('c', lldb.eFunctionNameTypeAuto)
>> self.assertTrue(list.GetSize() == 1)
>>
>> for sc in list:
>> try:
>>
>> self.assertTrue(sc.GetModule().GetFileSpec().GetFilename() == exe_name)
>> self.assertTrue(sc.GetSymbol().GetName() == 'c')
>> finally:
>> del sc
>>
>> finally:
>> del list
>>
>> The finally blocks ensure that the corresponding C++ objects are
>> destroyed, even if the function exits as a result of a Python exception
>> (e.g., if one of the assertion expressions is false and the code throws an
>> exception).  Since the objects are destroyed, the reference counts are back
>> to where they should be, and the orphaned module is closed when the target
>> is deleted.
>>
>> But this is ugly and maintaining it would be error prone.  Is there a
>> better way to address this?
>>
>> In general, it seems bad that our tests aren't well-isolated.  I
>> sympathize with the concern that re-starting LLDB for each test case would
>> slow down testing, but I'm also concerned that the state of LLDB for any
>> given test case can depend on what happened in the earlier cases.
>>
>> Adrian.
>>
>> ___
>> lldb-dev mailing list
>> lldb-dev@lists.llvm.org
>> http://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-dev
>>
>>
>
>
> --
> Oleksiy Vyalov | Software Engineer | ovya...@google.com
>
> ___
> lldb-dev mailing list
> lldb-dev@lists.llvm.org
> http://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-dev
>
>
___
lldb-dev mailing list
lldb-dev@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-dev


Re: [lldb-dev] Python object lifetimes affect the reliability of tests

2015-10-15 Thread Zachary Turner via lldb-dev
it doesn't appear to be a bug in my implementation.  So it seems like
everyone has been experiencing this problem, but Windows it just made a big
difference because of the mandatory file locks.  From the Python
dcoumentation ,

This function returns a tuple of three values that give information about
the exception that is currently being handled. The information returned is
specific both to the current thread and to the current stack frame. If the
current stack frame is not handling an exception, the information is taken
from the calling stack frame, or its caller, and so on until a stack frame
is found that is handling an exception. *Here, “handling an exception” is
defined as “executing or having executed an except clause.”* For any stack
frame, only information about the most recently handled exception is
accessible.

So within a given stack frame, if an exception has been handled before you,
then every frame and every variable reachable from that frame still has a
strong reference to it.

So it sounds like our solution of moving this exception handler into a
function or calling sys.exc_clear() is the right fix.

On Thu, Oct 15, 2015 at 11:43 AM Zachary Turner  wrote:

> It's not that simple.  A test method could be holding onto arbitrary
> resources which could in theory prevent cleanup.  tests can register their
> own cleanup handlers for example, and the teardown will call back into the
> cleanup handler.  So one of those handlers could be making the assumption
> that it can clean something up even though it can't because the test method
> is still holding onto some resources.
>
> I want to find out if this is a bug in my Python implementation, because
> it seems quite strange to me that sys.exc_info(), which is documented to
> return information about the exception *currently being processed*, still
> returns something after it is finished being processed.
>
> On Thu, Oct 15, 2015 at 11:36 AM Ryan Brown  wrote:
>
>> Couldn't we just change DeleteTarget to make sure everything is unmapped?
>>
>> On Thu, Oct 15, 2015 at 11:34 AM Zachary Turner via lldb-dev <
>> lldb-dev@lists.llvm.org> wrote:
>>
>>> To add more evidence for this, here's a small repro:
>>>
>>> import sys
>>>
>>> print "sys.exc_info() = ", "Empty" if sys.exc_info() == (None, None,
>>> None) else "Valid"
>>> try:
>>> raise Exception
>>> except Exception, e:
>>> print "sys.exc_info() = ", "Empty" if sys.exc_info() == (None, None,
>>> None) else "Valid"
>>> pass
>>>
>>> print "sys.exc_info() = ", "Empty" if sys.exc_info() == (None, None,
>>> None) else "Valid"
>>> print "e = ", "Bound" if 'e' in vars() else "Unbound"
>>> pass
>>>
>>> For me this prints
>>> sys.exc_info() =  Empty
>>> sys.exc_info() =  Valid
>>> sys.exc_info() =  Valid
>>> e =  Bound
>>>
>>> On Thu, Oct 15, 2015 at 11:21 AM Zachary Turner 
>>> wrote:
>>>
 We actually do already to the self.dbg.DeleteTarget(target), and that's
 the line that's failing.  The reason it's failing is because the 'sc'
 reference is still alive, which is holding an mmap, which causes a
 mandatory file lock on Windows.

 The diagnostics went pretty deep into python internals, but I think we
 might have figured it out.  I don't know if this is a bug in Python, but I
 think we'd probably need to ask Guido to be sure :)

 As far as we can tell, what happens is that on the exceptional codepath
 (e.g the assert fails), you walk back up the stack until you get to the
 except handler.  This exception handler is in TestCase.run().  After it
 handles the exception it goes and runs teardown.  However, for some reason,
 Python is still holding a strong reference to the *traceback*, even though
 we're completely out of the finally block.  What this means is that if you
 call `sys.exc_info()` *even after you've exited the finally block, it still
 returns info about the previous exception that's not even being handled
 anymore.  I would have expected this to be gone since there's no exception
 in-fligth anymore.  So basically, Python is still holding a reference to
 the active exception, the exception holds the stack frame, the stack frame
 holds the test method, the test method has locals, one of which is a
 SymbolList, a member of which is symbol context, which has the file locked.

 Our best guess is that if you have something like this:

 def foo():
 try:
# Do stuff
 except Exception, e:
pass
 # Do more stuff

 that if the exceptional path is executed, then both e and
 sys.exc_info() are alive *while* do more stuff is happening.  We've found
 two ways to fixthis:

 1) Change to this:
 def foo():
 try:
# Do stuff
 except Exception, e:
pass
 del e
 sys.exc_clear()
 # Do more stuff

 2) Put the try / except i

Re: [lldb-dev] Python object lifetimes affect the reliability of tests

2015-10-15 Thread Adrian McCarthy via lldb-dev
Thanks everyone.

To close the loop, we've address this problem with this patch:
http://reviews.llvm.org/rL250467



On Thu, Oct 15, 2015 at 11:49 AM, Zachary Turner  wrote:

> it doesn't appear to be a bug in my implementation.  So it seems like
> everyone has been experiencing this problem, but Windows it just made a big
> difference because of the mandatory file locks.  From the Python
> dcoumentation ,
>
> This function returns a tuple of three values that give information about
> the exception that is currently being handled. The information returned is
> specific both to the current thread and to the current stack frame. If the
> current stack frame is not handling an exception, the information is taken
> from the calling stack frame, or its caller, and so on until a stack frame
> is found that is handling an exception. *Here, “handling an exception” is
> defined as “executing or having executed an except clause.”* For any
> stack frame, only information about the most recently handled exception is
> accessible.
>
> So within a given stack frame, if an exception has been handled before
> you, then every frame and every variable reachable from that frame still
> has a strong reference to it.
>
> So it sounds like our solution of moving this exception handler into a
> function or calling sys.exc_clear() is the right fix.
>
> On Thu, Oct 15, 2015 at 11:43 AM Zachary Turner 
> wrote:
>
>> It's not that simple.  A test method could be holding onto arbitrary
>> resources which could in theory prevent cleanup.  tests can register their
>> own cleanup handlers for example, and the teardown will call back into the
>> cleanup handler.  So one of those handlers could be making the assumption
>> that it can clean something up even though it can't because the test method
>> is still holding onto some resources.
>>
>> I want to find out if this is a bug in my Python implementation, because
>> it seems quite strange to me that sys.exc_info(), which is documented to
>> return information about the exception *currently being processed*, still
>> returns something after it is finished being processed.
>>
>> On Thu, Oct 15, 2015 at 11:36 AM Ryan Brown  wrote:
>>
>>> Couldn't we just change DeleteTarget to make sure everything is unmapped?
>>>
>>> On Thu, Oct 15, 2015 at 11:34 AM Zachary Turner via lldb-dev <
>>> lldb-dev@lists.llvm.org> wrote:
>>>
 To add more evidence for this, here's a small repro:

 import sys

 print "sys.exc_info() = ", "Empty" if sys.exc_info() == (None, None,
 None) else "Valid"
 try:
 raise Exception
 except Exception, e:
 print "sys.exc_info() = ", "Empty" if sys.exc_info() == (None,
 None, None) else "Valid"
 pass

 print "sys.exc_info() = ", "Empty" if sys.exc_info() == (None, None,
 None) else "Valid"
 print "e = ", "Bound" if 'e' in vars() else "Unbound"
 pass

 For me this prints
 sys.exc_info() =  Empty
 sys.exc_info() =  Valid
 sys.exc_info() =  Valid
 e =  Bound

 On Thu, Oct 15, 2015 at 11:21 AM Zachary Turner 
 wrote:

> We actually do already to the self.dbg.DeleteTarget(target), and
> that's the line that's failing.  The reason it's failing is because the
> 'sc' reference is still alive, which is holding an mmap, which causes a
> mandatory file lock on Windows.
>
> The diagnostics went pretty deep into python internals, but I think we
> might have figured it out.  I don't know if this is a bug in Python, but I
> think we'd probably need to ask Guido to be sure :)
>
> As far as we can tell, what happens is that on the exceptional
> codepath (e.g the assert fails), you walk back up the stack until you get
> to the except handler.  This exception handler is in TestCase.run().  
> After
> it handles the exception it goes and runs teardown.  However, for some
> reason, Python is still holding a strong reference to the *traceback*, 
> even
> though we're completely out of the finally block.  What this means is that
> if you call `sys.exc_info()` *even after you've exited the finally block,
> it still returns info about the previous exception that's not even being
> handled anymore.  I would have expected this to be gone since there's no
> exception in-fligth anymore.  So basically, Python is still holding a
> reference to the active exception, the exception holds the stack frame, 
> the
> stack frame holds the test method, the test method has locals, one of 
> which
> is a SymbolList, a member of which is symbol context, which has the file
> locked.
>
> Our best guess is that if you have something like this:
>
> def foo():
> try:
># Do stuff
> except Exception, e:
>pass
> # Do more stuff
>
> that if the exceptional path is executed, then both e and
>