ASIO (think-async) version >= 1.22.1 crashes Pro Tools

I’m trying to find the reason why we can’t use ASIO versions 1.22.1 and up without crashing Pro Tools.

Note: I’m referring to ASIO from think-async.com, the networking library, not the audio driver ASIO.

When we use ASIO 1.22.1, Pro Tools crashes during plugin loading (during the splash screen). We get varying stack traces:

23541.732867,00103,0f09: Progress: Loading Plug-Ins: MyPlugin
23542.049963,0e50f,0e0f: Access Violation:
Stacktrace:
	0x14e9e4536 : asio::execution_context::service* asio::detail::service_registry::create<asio::detail::reactive_socket_service<asio::ip::tcp>, asio::io_context>(void*) + 134 (MyPlugin @ 0x14e4a5000)
	0x14e970ac8 : (null) + 200 (MyPlugin @ 0x14e4a5000)
	0x14e9eca22 : (null) + 2274 (MyPlugin @ 0x14e4a5000)
	0x14e9fc70b : (null) + 299 (MyPlugin @ 0x14e4a5000)
	0x14e4b796c : (null) + 44 (MyPlugin @ 0x14e4a5000)
	0x14e9fc509 : ACFRegisterPlugin + 9 (MyPlugin @ 0x14e4a5000)
... (redacted)
	0x105afe0fe : (null) + 5486 (Pro Tools @ 0x105af9000)
	0x109d0052e : start + 462 (dyld @ 0x109cfb000)

-----------------------------000041A710D63AF1--

42204.468548,00103,0e0d: Sys_PACE::GetWraptoolVersion - error for /Library/Application Support/Avid/Audio/Plug-Ins/MyPlugin.aaxplugin/: 0 ()
42204.533792,0fa0b,0e0f: Access Violation:
Stacktrace:
	0x136463536 : asio::execution_context::service* asio::detail::service_registry::create<asio::detail::reactive_socket_service<asio::ip::tcp>, asio::io_context>(void*) + 134 (MyPlugin @ 0x135f24000)
	0x1363efac8 : (null) + 200 (MyPlugin @ 0x135f24000)
	0x13646ba22 : (null) + 2274 (MyPlugin @ 0x135f24000)
	0x13647b70b : (null) + 299 (MyPlugin @ 0x135f24000)
	0x135f3696c : (null) + 44 (MyPlugin @ 0x135f24000)
	0x13647b509 : ACFRegisterPlugin + 9 (MyPlugin @ 0x135f24000)
... (redacted)
	0x106e49aec : (null) + 6716 (Pro Tools @ 0x106e45000)
	0x10fba052e : start + 462 (dyld @ 0x10fb9b000)

-----------------------------000041A710D63AF1--
Crashed Thread:        0  ASIO Thread 9  Dispatch queue: com.apple.main-thread

Exception Type:        EXC_BAD_ACCESS (SIGSEGV)
Exception Codes:       KERN_INVALID_ADDRESS at 0x0000000000000078
Exception Codes:       0x0000000000000001, 0x0000000000000078

Termination Reason:    Namespace SIGNAL, Code 11 Segmentation fault: 11
Terminating Process:   exc handler [13668]

VM Region Info: 0x78 is not in any region.  Bytes before following region: 68719476616
      REGION TYPE                    START - END         [ VSIZE] PRT/MAX SHRMOD  REGION DETAIL
      UNUSED SPACE AT START
--->  
      commpage (reserved)        1000000000-7000000000   [384.0G] ---/--- SM=NUL  ...(unallocated)

Thread 0 Crashed:: ASIO Thread 9 Dispatch queue: com.apple.main-thread
0   MyPlugin                       	       0x1609f120c asio::detail::conditionally_enabled_mutex::scoped_lock::scoped_lock(asio::detail::conditionally_enabled_mutex&) + 56 (conditionally_enabled_mutex.hpp:52)
1   MyPlugin                       	       0x1609f11fc asio::detail::conditionally_enabled_mutex::scoped_lock::scoped_lock(asio::detail::conditionally_enabled_mutex&) + 40 (conditionally_enabled_mutex.hpp:49)
2   MyPlugin                       	       0x1609f0e3c asio::detail::conditionally_enabled_mutex::scoped_lock::scoped_lock(asio::detail::conditionally_enabled_mutex&) + 36 (conditionally_enabled_mutex.hpp:51)
3   MyPlugin                       	       0x160a2d218 asio::detail::scheduler::init_task() + 36 (scheduler.ipp:184)
4   MyPlugin                       	       0x160a2d1c0 asio::detail::kqueue_reactor::init_task() + 28 (kqueue_reactor.ipp:138)
5   MyPlugin                       	       0x160a2d0c4 asio::detail::reactive_socket_service_base::reactive_socket_service_base(asio::execution_context&) + 64 (reactive_socket_service_base.ipp:35)
6   MyPlugin                       	       0x160ba8124 asio::detail::reactive_socket_service<asio::ip::tcp>::reactive_socket_service(asio::execution_context&) + 68 (reactive_socket_service.hpp:80)
7   MyPlugin                       	       0x160ba80d0 asio::detail::reactive_socket_service<asio::ip::tcp>::reactive_socket_service(asio::execution_context&) + 36 (reactive_socket_service.hpp:81)
8   MyPlugin                       	       0x160baa4f0 asio::execution_context::service* asio::detail::service_registry::create<asio::detail::reactive_socket_service<asio::ip::tcp>, asio::io_context>(void*) + 36 (service_registry.hpp:86)
9   MyPlugin                       	       0x1609ef1f8 asio::detail::service_registry::do_use_service(asio::execution_context::service::key const&, asio::execution_context::service* (*)(void*), void*) + 168 (service_registry.ipp:131)
10  MyPlugin                       	       0x160baa4c0 asio::detail::reactive_socket_service<asio::ip::tcp>& asio::detail::service_registry::use_service<asio::detail::reactive_socket_service<asio::ip::tcp> >(asio::io_context&) + 88 (service_registry.hpp:38)
11  MyPlugin                       	       0x160baa45c asio::detail::reactive_socket_service<asio::ip::tcp>& asio::use_service<asio::detail::reactive_socket_service<asio::ip::tcp> >(asio::io_context&) + 32 (io_context.hpp:40)
12  MyPlugin                       	       0x160baa3b8 asio::detail::io_object_impl<asio::detail::reactive_socket_service<asio::ip::tcp>, asio::any_io_executor>::io_object_impl<asio::io_context>(int, int, asio::io_context&) + 44 (io_object_impl.hpp:57)
13  MyPlugin                       	       0x160baa37c asio::detail::io_object_impl<asio::detail::reactive_socket_service<asio::ip::tcp>, asio::any_io_executor>::io_object_impl<asio::io_context>(int, int, asio::io_context&) + 52 (io_object_impl.hpp:59)
14  MyPlugin                       	       0x160baa310 asio::basic_socket_acceptor<asio::ip::tcp, asio::any_io_executor>::basic_socket_acceptor<asio::io_context>(asio::io_context&, asio::constraint<is_convertible<asio::io_context&, asio::execution_context&>::value, int>::type) + 48 (basic_socket_acceptor.hpp:157)
15  MyPlugin                       	       0x160ba6968 asio::basic_socket_acceptor<asio::ip::tcp, asio::any_io_executor>::basic_socket_acceptor<asio::io_context>(asio::io_context&, asio::constraint<is_convertible<asio::io_context&, asio::execution_context&>::value, int>::type) + 44 (basic_socket_acceptor.hpp:158)
16  MyPlugin                       	       0x160ba68d8 TcpListener::TcpListener(asio::io_context&) + 76 (TcpListener.cpp:12)
17  MyPlugin                       	       0x160ba699c TcpListener::TcpListener(asio::io_context&) + 36 (TcpListener.cpp:12)
... (redacted)
40  AppKit                        	       0x18ad54098 -[NSApplication _handleEvent:] + 60
41  AppKit                        	       0x18a9c8e30 -[NSApplication run] + 500
... (redacted)
46  Pro Tools Developer           	       0x10425f16c main + 5128
47  dyld                          	       0x187347e50 start + 2544

When I run a developer version with debugger attached I get a consistent stack trace:

objc_msgSend 0x00007ff811e2b1e9
-[NSCell resetCursorRect:inView:] 0x00007ff815496456
-[NSControl resetCursorRects] 0x00007ff81549638b
-[_NSTrackingAreaAKViewHelper updateTrackingAreasWithInvalidCursorRects:] 0x00007ff8159b296c
_NSViewSubViewMutationSafeApply 0x00007ff815c22e8c
-[_NSTrackingAreaAKViewHelper updateTrackingAreasWithInvalidCursorRects:] 0x00007ff8159b2a2a
_NSViewSubViewMutationSafeApply 0x00007ff815c22e8c
-[_NSTrackingAreaAKViewHelper updateTrackingAreasWithInvalidCursorRects:] 0x00007ff8159b2a2a
-[_NSTrackingAreaAKManager displayCycleUpdateStructuralRegions] 0x00007ff8159b0b02
__NSWindowGetDisplayCycleObserverForUpdateStructuralRegions_block_invoke 0x00007ff8153c3f3d
NSDisplayCycleObserverInvoke 0x00007ff8153beba1
NSDisplayCycleFlush 0x00007ff8153be7d1
CA::Transaction::run_commit_handlers(CATransactionPhase) 0x00007ff81a265f60
CA::Transaction::commit() 0x00007ff81a2649df
__62+[CATransaction(NSCATransaction) NS_setFlushesWithDisplayLink]_block_invoke 0x00007ff81545c9bf
___NSRunLoopObserverCreateWithHandler_block_invoke 0x00007ff815c74767
__CFRUNLOOP_IS_CALLING_OUT_TO_AN_OBSERVER_CALLBACK_FUNCTION__ 0x00007ff8122733e1
__CFRunLoopDoObservers 0x00007ff812273309
__CFRunLoopRun 0x00007ff812272866
CFRunLoopRunSpecific 0x00007ff812271e7f
RunCurrentEventLoopInMode 0x00007ff81c104766
ReceiveNextEventCommon 0x00007ff81c104396
_BlockUntilNextEventMatchingListInModeWithFilter 0x00007ff81c1042b3
_DPSNextEvent 0x00007ff8152fd2f3
-[NSApplication(NSEvent) _nextEventMatchingEventMask:untilDate:inMode:dequeue:] 0x00007ff8152fc174
-[NSApplication run] 0x00007ff8152ee7b7
DFW_EventLoop::RunApplicationEventLoop() 0x000000010f85e387
TApplication::Run() 0x000000010f66d0b0
Launch_Pro_Tools(char*, bool) 0x000000014f02197a
LaunchProTools 0x000000014f028791
main 0x000000010206ce7e
start 0x00000002028c9310

By trial and error I found that the problem starts with ASIO 1.22.1 and up. When using ASIO 1.20.0 I can get the plugin to load without crashes.

Now, I’m in the dark as to what might be going on here. My strongest suspicion at the moment is that Pro Tools itself might be using ASIO and that our plugin uses symbols which are not binary compatible with the newer ASIO versions. Is this theoretically possible?

What else could be going on here?

Any suggestions on how to approach this problem?

Pro Tools 2023.3.0 (universal)
Pro Tools Developer 2023.3.0 (arm64 & x86_64)
macOS 13.2.1

The plugin runs fine as VST3, AU & Standalone.

Thanks!

Have you tried setting

set_target_properties(YourTargetName PROPERTIES C_VISIBILITY_PRESET hidden)
set_target_properties(YourTargetName PROPERTIES CXX_VISIBILITY_PRESET hidden)
set_target_properties(YourTargetName PROPERTIES VISIBILITY_INLINES_HIDDEN TRUE)

Have you tried both the developer version and the release version of Pro Tools? Do you see the same results in both versions?

Also, how is the ASIO library linked to your plugin? As a static library, or a dynamic library? If you’re using it as a dynamic library, does switching to a static library make any difference?

Yes, (or almost, more on that later):

In my CMakeLists.txt I did:

set(CMAKE_CXX_VISIBILITY_PRESET hidden)
set(CMAKE_VISIBILITY_INLINES_HIDDEN ON)

And in my vcpkg triplet files I added:

set(VCPKG_C_FLAGS "${VCPKG_C_FLAGS} -fvisibility=hidden -fvisibility-inlines-hidden")
set(VCPKG_CXX_FLAGS "${VCPKG_CXX_FLAGS} -fvisibility=hidden -fvisibility-inlines-hidden")

Now that you mention it I realise that I didn’t set the CMAKE_C_VISIBILITY_PRESET which I will try as well to be sure.

EDIT: although good practice to add set(CMAKE_C_VISIBILITY_PRESET hidden), it doesn’t help in this case.

I’ve tried both the developer version (arm64 & x86_64) and the release versions. The first 3 stacktraces in my original post are from release builds, the 4th trace is from a developer build.

I am linking statically, but ASIO is a header-only library so I suppose there is not really any linking going on?

Maybe add a dummy namespace around asio

namespace myApp
{
#include “adio.h”
}

1 Like

That’s a super interesting suggestion! Thanks!

@ruurdadema
I’m experiencing a similar crash at both Pro Tools and Ableton live, did you find a way to resolve it?

I solved it by using ASIO 1.18.0 specifically.

For this reason my vcpkg.json looks like this:

{
  "name": "app name",
  "version-string": "0.1.0",
  "dependencies": [
    "asio",
  ],
  "overrides": [
    { "name": "asio", "version": "1.18.0" }
  ],
  "builtin-baseline": "2f56fdad4bcf43c21ec6f952cf7b91c8c43c5c0d"
}

If I ever were to use a newer version of ASIO I would try the suggestion from @otristan and wrap ASIO in a dummy namespace, but at this moment I haven’t tried that.

Thank you for the information.
I’m using ASIO standalone version 1.28 which is integrated in WebSocketPP library.
I found a problem in kqueue and by disabling it using ASIO_DISABLE_KQUEUE looks like it works fine now. Not sure about the implications of it though, will check it further. Quite new to asio implementation.

1 Like

Maybe add a dummy namespace around asio

namespace myApp
{
#include “adio.h”
}

This produces errors like:

error: no template named 'is_error_code_enum'; did you mean '::std::is_error_code_enum'?
error: no type named 'string' in namespace 'myApp::std'; did you mean '::std::string'?

And a lot more of the same kind. Some problems can be solved by typedeffing or putting symbols in the right namespace, but a lot of problem can’t be solved (afaik).

To make things worse, our plugin started crashing in Ableton Live 11 on Intel. The strack trace points to asio kqueue facilities:

asio::detail::kqueue_reactor::allocate_descriptor_state() (in auxCord) (kqueue_reactor.ipp:527)
asio::detail::reactive_socket_service_base::do_open(asio::detail::reactive_socket_service_base::base_implementation_type&, int, int, int, std::__1::error_code&) (in auxCord) (reactive_socket_service_base.ipp:185)
asio::basic_socket_acceptor<asio::ip::tcp, asio::execution::any_executor<asio::execution::context_as_t<asio::execution_context&>, asio::execution::detail::blocking::never_t<0>, asio::execution::prefer_only<asio::execution::detail::blocking::possibly_t<0>>, asio::execution::prefer_only<asio::execution::detail::outstanding_work::tracked_t<0>>, asio::execution::prefer_only<asio::execution::detail::outstanding_work::untracked_t<0>>, asio::execution::prefer_only<asio::execution::detail::relationship::fork_t<0>>, asio::execution::prefer_only<asio::execution::detail::relationship::continuation_t<0>>>>::open(asio::ip::tcp const&) (in auxCord) (basic_socket_acceptor.hpp:463)

which makes me worry that Pro Tools and Ableton use different versions of ASIO and both conflict with ASIO in our plugin.

Does anyone have any other ideas or suggestions?

I tried the suggestion of disabling kqueue by defining ASIO_DISABLE_KQUEUE, but unfortunately this introduces problems elsewhere, most notably during a call to cancel on a udp socket:

asio::detail::select_reactor::cancel_ops_unlocked(int, std::__1::error_code const&) (in auxCord) (select_reactor.ipp:320)
asio::detail::select_reactor::cancel_ops(int, asio::detail::select_reactor::per_descriptor_data&) (in auxCord) (select_reactor.ipp:166)

In Pro Tools it will hang at this point instead of crashing.

Allright, I figured it out.

ASIO allows to define ASIO_DISABLE_VISIBILITY to disable any symbol visibility pragmas. After adding this, the plugin runs correctly in both Ableton and Pro Tools.

I also added ASIO_SEPARATE_COMPILATION to put as many symbols in a separate translation unit, but this doesn’t seem to make a practical difference (ie. with ASIO_DISABLE_VISIBILITY but without ASIO_SEPARATE_COMPILATION still solves the problem).

With this solution in place I can now also use kqueue again, which I think is great.

For reference: Using, Building, and Configuring Asio