apache / cordova-plugin-media

Apache Cordova Media Plugin
https://cordova.apache.org/
Apache License 2.0
388 stars 768 forks source link

iOS: Crash in [CDVSound startPlayingAudio:] with version 3.0.1 and 5.0.2 #174

Open sjkummer opened 6 years ago

sjkummer commented 6 years ago

Hi there,

I am receiving crashreports from my users (via iTunesConnect) related to [CDVSound startPlayingAudio:]

It is very hard to reproduce this issue and it does not occur very often. May be releated to specific usage, devices or threading.

I wonder if this issue is already known and potentially fixed. I'll upgrade to version 5.0.1 and let you know if it still occurs.

Full logfile cdv.crash.txt

Interesting log sections:

Thread 32 Crashed:
0   AVFAudio                        0x000000018a25880c AVAudioPlayerCpp::AQOutputCallbackCore(OpaqueAudioQueue*, AudioQueueBuffer*) + 180 (AVAudioPlayerCpp.mm:1250)
1   AVFAudio                        0x000000018a257e84 AVAudioPlayerCpp::prepareToPlayQueue() + 224 (AVAudioPlayerCpp.mm:883)
2   AVFAudio                        0x000000018a257e84 AVAudioPlayerCpp::prepareToPlayQueue() + 224 (AVAudioPlayerCpp.mm:883)
3   AVFAudio                        0x000000018a257fe0 AVAudioPlayerCpp::playQueue(AudioTimeStamp const*) + 112 (AVAudioPlayerCpp.mm:956)
4   AVFAudio                        0x000000018a256760 AVAudioPlayerCpp::play() + 80 (AVAudioPlayerCpp.mm:667)
5   AVFAudio                        0x000000018a218414 -[AVAudioPlayer play] + 52 (AVAudioPlayer.mm:455)
6   MYAPP                           0x00000001041a16d4 __30-[CDVSound startPlayingAudio:]_block_invoke + 1648 (CDVSound.m:402)
7   libdispatch.dylib               0x00000001841b4aa0 _dispatch_call_block_and_release + 24 (init.c:994)
8   libdispatch.dylib               0x00000001841b4a60 _dispatch_client_callout + 16 (object.m:507)
9   libdispatch.dylib               0x00000001841bbb84 _dispatch_queue_override_invoke$VARIANT$mp + 716 (inline_internal.h:2500)
10  libdispatch.dylib               0x00000001841c1cac _dispatch_root_queue_drain + 588 (inline_internal.h:2539)
11  libdispatch.dylib               0x00000001841c19fc _dispatch_worker_thread3 + 120 (queue.c:6092)
12  libsystem_pthread.dylib         0x00000001844e7fac _pthread_wqthread + 1176 (pthread.c:2297)
13  libsystem_pthread.dylib         0x00000001844e7b08 start_wqthread + 4
sjkummer commented 6 years ago

Hi,

Unfortunately, I still got some crash reports after upgrading to version 5.0.2

I may have to add, that I am playing two files at the same time.

To me, this looks like a multi threading problem. As far as I can see this cordova plugin is not thread safe, is this correct?

Investigation:

  1. In my crash dump / stacktrace, I got multiple threads that are currently in [CDVSound prepareToPlay]
  2. [CDVSound prepareToPlay] starts with a [self.commandDelegate runInBackground:^{
  3. runInBackground is just a dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), block);
  4. The dispatch_get_global_queue is a concurrent queue, so it does not help for thread safety / thread sync of the executed tasks, see: https://developer.apple.com/documentation/dispatch/1452927-dispatch_get_global_queue

Please let me know, if I am missing something 😳

Full Log: full_crash_log_5.0.1.txt

Exception Type:  EXC_BAD_ACCESS (SIGSEGV)
Exception Subtype: KERN_INVALID_ADDRESS at 0x41534e57171614cb
VM Region Info: 0x41534e57171614cb is not in any region.  Bytes after previous region: 4707192163435680972  
      REGION TYPE                      START - END             [ VSIZE] PRT/MAX SHRMOD  REGION DETAIL
      MALLOC_NANO (reserved) 00000001d8000000-00000001e0000000 [128.0M] rw-/rwx SM=NUL  ...(unallocated)
--->  
      UNUSED SPACE AT END

Termination Signal: Segmentation fault: 11
Termination Reason: Namespace SIGNAL, Code 0xb
Terminating Process: exc handler [0]
Triggered by Thread:  14

Thread 14 name:
Thread 14 Crashed:
0   AVFAudio                        0x000000018a9a880c AVAudioPlayerCpp::AQOutputCallbackCore(OpaqueAudioQueue*, AudioQueueBuffer*) + 180 (AVAudioPlayerCpp.mm:1250)
1   AVFAudio                        0x000000018a9a7e84 AVAudioPlayerCpp::prepareToPlayQueue() + 224 (AVAudioPlayerCpp.mm:883)
2   AVFAudio                        0x000000018a9a7e84 AVAudioPlayerCpp::prepareToPlayQueue() + 224 (AVAudioPlayerCpp.mm:883)
3   AVFAudio                        0x000000018a9a7fe0 AVAudioPlayerCpp::playQueue(AudioTimeStamp const*) + 112 (AVAudioPlayerCpp.mm:956)
4   AVFAudio                        0x000000018a9a6760 AVAudioPlayerCpp::play() + 80 (AVAudioPlayerCpp.mm:667)
5   AVFAudio                        0x000000018a968414 -[AVAudioPlayer play] + 52 (AVAudioPlayer.mm:455)
6   MYAPP                               0x0000000102b53484 __30-[CDVSound startPlayingAudio:]_block_invoke + 1648 (CDVSound.m:418)
7   libdispatch.dylib               0x0000000184904aa0 _dispatch_call_block_and_release + 24 (init.c:994)
8   libdispatch.dylib               0x0000000184904a60 _dispatch_client_callout + 16 (object.m:507)
9   libdispatch.dylib               0x0000000184940548 _dispatch_queue_override_invoke$VARIANT$armv81 + 700 (inline_internal.h:2500)
10  libdispatch.dylib               0x00000001849463c4 _dispatch_root_queue_drain + 592 (inline_internal.h:2539)
11  libdispatch.dylib               0x0000000184946110 _dispatch_worker_thread3 + 112 (queue.c:6092)
12  libsystem_pthread.dylib         0x0000000184c37fac _pthread_wqthread + 1176 (pthread.c:2297)
13  libsystem_pthread.dylib         0x0000000184c37b08 start_wqthread + 4
sjkummer commented 6 years ago

@janpio : Is there a change that this bug is going to be fixed? As far as I can see, there is no more active development, nor are PullRequests merged... 😕

janpio commented 6 years ago

Apache Cordova is an Open Source project with a very limited set of active volunteer maintainers. Currently the focus is on a) finishing migration of issues from JIRA to GitHub and adapting all the processes and rules that go with it (e.g. by labeling new issues etc) and b) working on releasing and finishing new versions of everything but the plugins (CLI, platforms, other libraries and tooling). Several people are focusing on cleaning up the code base, to enable us to create more stable releases in the future quicker.

If you have a good understanding of your issue for this plugin and might be able to create a PR, please go ahead and do so! I personally won't be able to review it as I don't do Obj-C, but at least something is there and the day will come when we will be able to look at the plugin PRs and issues with some more effort as well. We of course can't just merge stuff without people reviewing the PRs and making sure they actually improve the situation. Unfortunately quite often one issue is fixed, while 5 others are created ;)

AvnerAviram commented 5 years ago

Hi @sjkummer We are facing the same crash issue on IOS with latest plugin release (5.0.2) - seeing it only from production logs - very hard to reproduce. Did you have any solution or workaround for this issue?

sjkummer commented 5 years ago

@Javier84 I am now caching all files on the local file system and make sure that everything is completely loaded before playing. No more crashes in iTunes Connect.

david-clang commented 5 years ago

Hi @sjkummer " I am now caching all files on the local file system and make sure that everything is completely loaded before playing." Which APIs have you used? Can you show your code?Thanx!

david-clang commented 5 years ago

If the whilt loop calls play 100 times, there is a big chance that it will crash. If you use serial queue, you can avoid crash.

In my own project, I use serial queue call to play to avoid crashes,

crash code:

- (void)buttonAction {
    NSInteger testCount = 100;
    while (testCount) {
        testCount--;
        AVAudioPlayer *player = [self unusedPlayerWithPath:path];
        dispatch_async(dispatch_get_global_queue(0, 0), ^{
            if (player) {
                [player play];
            }
        });
    }
}

safe code:

- (void)buttonAction {
    NSInteger testCount = 100;
    while (testCount) {
        testCount--;
        AVAudioPlayer *player = [self unusedPlayerWithPath:path];
        dispatch_async(self.serialQueue,  ^{
            if (player) {
                [player play];
            }
        });
    }
}

Cache all the files on the local file system, will it crash if you call the call 100 times in a loop?@sjkummer