Thread overview
Thread exits immediately with no reason.
Dec 20, 2021
solidstate1991
Dec 21, 2021
Ali Çehreli
Dec 21, 2021
bauss
Dec 21, 2021
Dennis
Dec 21, 2021
solidstate1991
Dec 21, 2021
Ali Çehreli
Dec 21, 2021
solidstate1991
Dec 21, 2021
solidstate1991
December 20, 2021

Here's this function, which serves as a thread entry point: https://github.com/ZILtoid1991/iota/blob/main/source/iota/audio/wasapi.d#L220

The problem is, that even with disabling all error-handling that would allow to shut down the thread safely, the thread only runs that while loop once.

However, if I set my debugger to have a breakpoint right at the loop entry it can kinda loop, however the real-time capabilities cease to work properly.

I'm using this handy application to debug my library: https://github.com/ZILtoid1991/iota/blob/main/testsource/app.d#L54

After the referenced line (where I start my audio thread) I also set the main program to wait 10 seconds. At least the audio thread just exits for some reason instead of being suspended by Thread.wait().

December 20, 2021
On 12/20/21 3:56 PM, solidstate1991 wrote:

> The problem is, that even with disabling all error-handling that would
> allow to shut down the thread safely, the thread only runs that while
> loop once.

I bet it's throwing an Error. Call your thread entry function from a try-catch wrapping function to see whether that's the case:

// Rename existing function:
protected void audioThreadImpl() @nogc nothrow {
  // ...
}

// New function
protected void audioThread() @nogc nothrow {
  try {
    audioThreadImpl();

  } catch (Error err) {
    stderr.writefln!"ERROR: %s"(err);
  }
}

That should print a call stack. You can catch Throwable instead of Error but with nothrow, it's guaranteed that it's not an Exception.

Note: nothrow means "does not throw Exception". Errors can still be thrown.

Ali

December 21, 2021
On Tuesday, 21 December 2021 at 01:13:10 UTC, Ali Çehreli wrote:
>
> Note: nothrow means "does not throw Exception". Errors can still be thrown.
>
> Ali

Which sort of makes sense since they're in theory "unrecoverable", but the name is sort of misleading because of this minor detail. It should at the very least warn people about functions that may throw errors.
December 21, 2021
On Tuesday, 21 December 2021 at 07:08:53 UTC, bauss wrote:
> It should at the very least warn people about functions that may throw errors.

What is "It"? I was looking to make a spec PR, but it already says here:

https://dlang.org/spec/function.html#nothrow-functions

> Nothrow functions can only throw exceptions derived from class Error.

December 21, 2021

On Tuesday, 21 December 2021 at 01:13:10 UTC, Ali Çehreli wrote:

>

I bet it's throwing an Error. Call your thread entry function from a try-catch wrapping function to see whether that's the case:

// Rename existing function:
protected void audioThreadImpl() @nogc nothrow {
// ...
}

// New function
protected void audioThread() @nogc nothrow {
try {
audioThreadImpl();

} catch (Error err) {
stderr.writefln!"ERROR: %s"(err);
}
}

That should print a call stack. You can catch Throwable instead of Error but with nothrow, it's guaranteed that it's not an Exception.

Note: nothrow means "does not throw Exception". Errors can still be thrown.

Ali

I couldn't add those lines unfortunately, but I do get an exception in a destructor at line 218 of wasapi.d. It's access violation executing a location.

December 21, 2021
On 12/21/21 10:07 AM, solidstate1991 wrote:

> I couldn't add those lines unfortunately,

Perhaps I had typos? Or the code is not yours to modify? In any case, you should be able to introduce a top level thread entry function and put the try-catch in there.

> but I do get an exception in a
> destructor at line 218 of `wasapi.d`. It's access violation executing a
> location.

If garbage-collected objects are involved, it may be because destructors are executed at indeterminate times, potentially after their members are destroyed. I haven't studied the code to be sure but for example, eventHandle may have already been destroyed when executing the following line:


https://github.com/ZILtoid1991/iota/blob/main/source/iota/audio/wasapi.d#L218

A solution is to manage the destruction of objects at known times e.g. by calling destroy() explicitly.

Ali

December 21, 2021
Well, it seems like it's an error on the WASAPI side. I totally disabled error handling (including the switch-case thingy), then GetBuffer returns with an error code indicating buffer is too large.
December 21, 2021

On Tuesday, 21 December 2021 at 19:00:01 UTC, solidstate1991 wrote:

>

Well, it seems like it's an error on the WASAPI side. I totally disabled error handling (including the switch-case thingy), then GetBuffer returns with an error code indicating buffer is too large.

The solution was to call ResetEvent() on the event handle, then to tinker a little bit with destructors, etc.