Jump to page: 1 2 3
Thread overview
Debugging silent exit of threads in Phobos calls
Jun 01, 2018
Russel Winder
Jun 01, 2018
ketmar
Jun 01, 2018
Russel Winder
Jun 01, 2018
ketmar
Jun 01, 2018
Russel Winder
Jun 01, 2018
ketmar
Jun 01, 2018
Russel Winder
Jun 01, 2018
ketmar
Jun 01, 2018
Russel Winder
Jun 01, 2018
Ali Çehreli
Jun 01, 2018
Russel Winder
Jun 01, 2018
Russel Winder
Re: Debugging silent exit of threads in Phobos calls (bugzilla issue submitted)
Jun 02, 2018
Russel Winder
Jun 02, 2018
Kagamin
Jun 02, 2018
Russel Winder
Jun 18, 2018
Russel Winder
Jun 01, 2018
Russel Winder
Jun 01, 2018
Ali Çehreli
Jun 01, 2018
Russel Winder
June 01, 2018
So I had a play and gdb seems to be useless for trying to find out why calls to std.concurrency.receive exit silently.

Obviously std.concurrency.receive should never terminate a thread, and it should never terminate a thread silently, but given that it clearly does (using dmd 2.080 from d-apt on Debian Sid) how is one to find out useful information as to why it is exiting silently.


-- 
Russel.
===========================================
Dr Russel Winder      t: +44 20 7585 2200
41 Buckmaster Road    m: +44 7770 465 077
London SW11 1EN, UK   w: www.russel.org.uk


June 01, 2018
On 6/1/18 7:12 AM, Russel Winder wrote:
> So I had a play and gdb seems to be useless for trying to find out why
> calls to std.concurrency.receive exit silently.
> 
> Obviously std.concurrency.receive should never terminate a thread, and
> it should never terminate a thread silently, but given that it clearly
> does (using dmd 2.080 from d-apt on Debian Sid) how is one to find out
> useful information as to why it is exiting silently.

I remember something like a receive thread that throws terminates silently. Do a try/catch to see if it's that.

-Steve
June 01, 2018
Steven Schveighoffer wrote:

> On 6/1/18 7:12 AM, Russel Winder wrote:
>> So I had a play and gdb seems to be useless for trying to find out why
>> calls to std.concurrency.receive exit silently.
>> Obviously std.concurrency.receive should never terminate a thread, and
>> it should never terminate a thread silently, but given that it clearly
>> does (using dmd 2.080 from d-apt on Debian Sid) how is one to find out
>> useful information as to why it is exiting silently.
>
> I remember something like a receive thread that throws terminates silently. Do a try/catch to see if it's that.
>
> -Steve

yeah. if it receives something it doesn't expect (and there is no `Variant` clause to catch it), it throws. and exceptions from threads are silently dropped on the floor -- along with the dead threads. so it is better to always wrap your threads in `try/catch`, and at least log an exception.
June 01, 2018
On Fri, 2018-06-01 at 09:31 -0400, Steven Schveighoffer via Digitalmars-d-learn wrote:
> On 6/1/18 7:12 AM, Russel Winder wrote:
> > So I had a play and gdb seems to be useless for trying to find out
> > why
> > calls to std.concurrency.receive exit silently.
> > 
> > Obviously std.concurrency.receive should never terminate a thread,
> > and
> > it should never terminate a thread silently, but given that it
> > clearly
> > does (using dmd 2.080 from d-apt on Debian Sid) how is one to find
> > out
> > useful information as to why it is exiting silently.
> 
> I remember something like a receive thread that throws terminates silently. Do a try/catch to see if it's that.

Tried to catch Exception but that failed to work, fortunately remembered to catch Throwable and it turned out to be a

receive threw an exception core.exception.AssertError@/usr/include/dmd/phobos/std/variant.d(323):

It seems that the type frontend_manager.FrontendAppeared is not the same as frontend_manager.FrontendAppeared. :-( Who knew.

-- 
Russel.
===========================================
Dr Russel Winder      t: +44 20 7585 2200
41 Buckmaster Road    m: +44 7770 465 077
London SW11 1EN, UK   w: www.russel.org.uk


June 01, 2018
On Fri, 2018-06-01 at 16:37 +0300, ketmar via Digitalmars-d-learn wrote:
> 
[…]
> yeah. if it receives something it doesn't expect (and there is no
> `Variant`
> clause to catch it), it throws. and exceptions from threads are
> silently
> dropped on the floor -- along with the dead threads. so it is better
> to
> always wrap your threads in `try/catch`, and at least log an
> exception.

It seems that in the case he presence of the Variant doesn't matter.

The message sent is of type frontend_manager.FrontendAppeared and one of the receive types is frontend_manager.FrontendAppreared yet this fails to match but it is not treated as a Variant.

The stack trace is:


ControlWindowDaemon: receive threw an exception core.exception.AssertError@/usr/include/dmd/phobos/std/variant.d(323): FrontendAppeared
----------------
??:? _d_assert_msg [0x55e72826]
??:? bool std.variant.VariantN!(32uL).VariantN.handler!(frontend_manager.FrontendAppeared).handler(std.variant.VariantN!(32uL).VariantN.OpID, ubyte[32]*, void*).tryPutting(frontend_manager.FrontendAppeared*, TypeInfo, void*) [0x55ba1dc1]
??:? long std.variant.VariantN!(32uL).VariantN.handler!(frontend_manager.FrontendAppeared).handler(std.variant.VariantN!(32uL).VariantN.OpID, ubyte[32]*, void*) [0x55ba1949]
??:? inout @property inout(frontend_manager.FrontendAppeared) std.variant.VariantN!(32uL).VariantN.get!(frontend_manager.FrontendAppeared).get() [0x55b9fadf]
??:? void std.concurrency.Message.map!(void function(frontend_manager.FrontendAppeared) @safe*).map(void function(frontend_manager.FrontendAppeared) @safe*) [0x55b9fa9c]
??:? bool std.concurrency.MessageBox.get!(void function(frontend_manager.FrontendAppeared) @safe*, void function(frontend_manager.FrontendDisappeared) @safe*, void delegate(std.concurrency.OwnerTerminated) @safe).get(scope void function(frontend_manager.FrontendAppeared) @safe*, scope void function(frontend_manager.FrontendDisappeared) @safe*, scope void delegate(std.concurrency.OwnerTerminated) @safe).onStandardMsg(ref std.concurrency.Message) [0x55b9f3b4]
??:? bool std.concurrency.MessageBox.get!(void function(frontend_manager.FrontendAppeared) @safe*, void function(frontend_manager.FrontendDisappeared) @safe*, void delegate(std.concurrency.OwnerTerminated) @safe).get(scope void function(frontend_manager.FrontendAppeared) @safe*, scope void function(frontend_manager.FrontendDisappeared) @safe*, scope void delegate(std.concurrency.OwnerTerminated) @safe).scan(ref std.concurrency.List!(std.concurrency.Message).List) [0x55b9f834]
??:? bool std.concurrency.MessageBox.get!(void function(frontend_manager.FrontendAppeared) @safe*, void function(frontend_manager.FrontendDisappeared) @safe*, void delegate(std.concurrency.OwnerTerminated) @safe).get(scope void function(frontend_manager.FrontendAppeared) @safe*, scope void function(frontend_manager.FrontendDisappeared) @safe*, scope void delegate(std.concurrency.OwnerTerminated) @safe) [0x55b9f2c8]
??:? void std.concurrency.receive!(void function(frontend_manager.FrontendAppeared) @safe*, void function(frontend_manager.FrontendDisappeared) @safe*, void delegate(std.concurrency.OwnerTerminated) @safe).receive(void function(frontend_manager.FrontendAppeared) @safe*, void function(frontend_manager.FrontendDisappeared) @safe*, void delegate(std.concurrency.OwnerTerminated) @safe) [0x55b9f0ec]
??:? void control_window.runControlWindowDaemon() [0x55b9edb3]
??:? void std.concurrency._spawn!(void function()*)._spawn(bool, void function()*).exec() [0x55ba3f4f]
??:? void core.thread.Thread.run() [0x55e739a7]
??:? thread_entryPoint [0x55ea5267]
??:? [0xf79bd5a9]




-- 
Russel.
===========================================
Dr Russel Winder      t: +44 20 7585 2200
41 Buckmaster Road    m: +44 7770 465 077
London SW11 1EN, UK   w: www.russel.org.uk


June 01, 2018
Russel Winder wrote:

> On Fri, 2018-06-01 at 16:37 +0300, ketmar via Digitalmars-d-learn
> wrote:
>> 
> […]
>> yeah. if it receives something it doesn't expect (and there is no
>> `Variant` clause to catch it), it throws. and exceptions from threads are
>> silently dropped on the floor -- along with the dead threads. so it is better
>> to always wrap your threads in `try/catch`, and at least log an
>> exception.
>
> It seems that in the case he presence of the Variant doesn't matter.
>
> The message sent is of type frontend_manager.FrontendAppeared and one
> of the receive types is frontend_manager.FrontendAppreared yet this
> fails to match but it is not treated as a Variant. 
>
> The stack trace is:

it looks like "// type T is not constructible from A" phobos assertion triggered. that is, std.variant cannot wrap the struct, and all hell breaks loose.
June 01, 2018
On 06/01/2018 04:12 AM, Russel Winder wrote:

> Obviously std.concurrency.receive should never terminate a thread, and
> it should never terminate a thread silently, but given that it clearly
> does (using dmd 2.080 from d-apt on Debian Sid) how is one to find out
> useful information as to why it is exiting silently.

It sounds like one of the message handlers is throwing. In that case, it sounds like a good idea to wrap each handler with try-catch.

Ali

P.S. In case it's useful for someone, and I know it's not for the same case, I include something about exceptions in a worker thread, which shows that it's possible to receive a shared(Exception):


http://ddili.org/ders/d.en/concurrency.html#ix_concurrency.exception,%20concurrency

However, it fails to suggest catching Throwable or Error at least for debugging.
June 01, 2018
On Fri, 2018-06-01 at 07:59 -0700, Ali Çehreli via Digitalmars-d-learn wrote:
> On 06/01/2018 04:12 AM, Russel Winder wrote:
> 
> > Obviously std.concurrency.receive should never terminate a thread,
> > and
> > it should never terminate a thread silently, but given that it
> > clearly
> > does (using dmd 2.080 from d-apt on Debian Sid) how is one to find
> > out
> > useful information as to why it is exiting silently.
> 
> It sounds like one of the message handlers is throwing. In that case,
> it
> sounds like a good idea to wrap each handler with try-catch.

The try/catch allows one to see that there appears to be a problem inside Phobos, i.e. it determines that x.X is not the same type as x.X and throws an assertion error. To handle this in the application is to accept that Phobos is broken and not fixable. :-(

Unless this is actually just that x.X is not x.X even though it is x.X. In this case it would be a module naming error in D and Phobos is not wrong.

> […]
-- 
Russel.
===========================================
Dr Russel Winder      t: +44 20 7585 2200
41 Buckmaster Road    m: +44 7770 465 077
London SW11 1EN, UK   w: www.russel.org.uk


June 01, 2018
On Fri, 2018-06-01 at 17:53 +0300, ketmar via Digitalmars-d-learn wrote:
> 
[…]
> it looks like "// type T is not constructible from A" phobos
> assertion
> triggered. that is, std.variant cannot wrap the struct, and all hell
> breaks
> loose.

An instance of FrontendAppeared is created in frontend_manager module and sent to the actor defined in control_window module which has:

    import frontend_manager: FrontendAppeared

It seems the symbol FrontendAppeared in control_window is matching the
FrontendAppeared type of the message sent, and yet the assertion fails.

-- 
Russel.
===========================================
Dr Russel Winder      t: +44 20 7585 2200
41 Buckmaster Road    m: +44 7770 465 077
London SW11 1EN, UK   w: www.russel.org.uk


June 01, 2018
On 6/1/18 10:53 AM, ketmar wrote:
> Russel Winder wrote:
> 
>> On Fri, 2018-06-01 at 16:37 +0300, ketmar via Digitalmars-d-learn
>> wrote:
>>>
>> […]
>>> yeah. if it receives something it doesn't expect (and there is no
>>> `Variant` clause to catch it), it throws. and exceptions from threads are
>>> silently dropped on the floor -- along with the dead threads. so it is better
>>> to always wrap your threads in `try/catch`, and at least log an
>>> exception.
>>
>> It seems that in the case he presence of the Variant doesn't matter.
>>
>> The message sent is of type frontend_manager.FrontendAppeared and one
>> of the receive types is frontend_manager.FrontendAppreared yet this
>> fails to match but it is not treated as a Variant.
>> The stack trace is:
> 
> it looks like "// type T is not constructible from A" phobos assertion triggered. that is, std.variant cannot wrap the struct, and all hell breaks loose.

That assertion is something that should never happen. Something is wrong with the type checking here.

If you look up earlier, clearly the type id matches. There is something weird about that static if that is not working.

Can you put in some more debug messages and see what the exact types of A and T are? Just put it right before the assert.

-Steve
« First   ‹ Prev
1 2 3