My iphone app get locked malloc. If I press pause button in Xcode it pauses in OSSpinLockLock$VARIANT$mp function.
#0 0x95dfbc2d in OSSpinLockLock$VARIANT$mp ()
#1 0x95dc2613 in szone_malloc_should_clear ()
#2 0x95dc366b in szone_malloc ()
#3 0x95df9962 in malloc_zone_malloc ()
#4 0x95dfa882 in malloc ()
#5 0x0219743a in operator new(unsigned long) ()
if I press continue and then pause again then it always shows same stack trace.
Look at your other threads. One of them is likely blocked inside of a malloc or free as well and the two are deadlocked against each other.
A somewhat common cause of this is allocating memory inside of a signal handler (which you should never do). You'll see this especially if you have some kind of "crash catcher" in your system, and inside of the handler you do complex operations.
Related
See example below:
import 'dart:async';
Future<void> main(List<String> arguments) async {
try {
await someMethod();
} catch (e, st) {
print("error: ${e}");
print("st : ${st}");
}
}
Future<void> someMethod() async {
final completer = Completer.sync();
_scheduleCompletion(completer);
await completer.future;
}
Future<void> _scheduleCompletion(Completer completer) async {
Future.delayed(Duration(milliseconds: 1), () {
try {
[][0]; // simulating error
completer.complete();
} catch (e, st) {
completer.completeError("error occured", st);
}
});
}
I am receiving following output:
#0 List.[] (dart:core-patch/growable_array.dart:254:60)
#1 _scheduleCompletion.<anonymous closure> (file:///home/work/stuff/projects/dart-async-exceptions/bin/dart_async_exceptions.dart:26:9)
#2 new Future.delayed.<anonymous closure> (dart:async/future.dart:315:39)
#3 Timer._createTimer.<anonymous closure> (dart:async-patch/timer_patch.dart:18:15)
#4 _Timer._runTimers (dart:isolate-patch/timer_impl.dart:395:19)
#5 _Timer._handleMessage (dart:isolate-patch/timer_impl.dart:426:5)
#6 _RawReceivePortImpl._handleMessage (dart:isolate-patch/isolate_patch.dart:184:12)
As you can see stacktrace does not allow you to see what steps led to error. What I expect is something like:
[anonymous closure, where error actually happens]
[someMethod]
[main]
while instead I see only last part.
I know there is package, called stack_trace, that allows you to "wrap your whole program in Chain.capture and you will be happy". Unfortunately my real-world case is not that simple and I can not simply "wrap my program" in "Chain.capture".
Another reason on not using "Chain.capture" thing is that in some cases it's onError handler gets even worse stacktrace vs. simple try/catch block .
Also I would like to understand why this is happening and what should I do to fix my program so part of valuable trace is not lost.
UPDATE (based on Irn's answer):
Let's re-write someMethod not to use completer, but rather call another async method:
Future<void> someMethod() async {
await someOtherMethod();
}
Future<void> someOtherMethod() async {
throw "another error";
}
In that case I will have following trace:
#0 someOtherMethod (file:///home/work/stuff/projects/dart-async-exceptions/bin/dart_async_exceptions_original.dart:24:3)
<asynchronous suspension>
#1 someMethod (file:///home/work/stuff/projects/dart-async-exceptions/bin/dart_async_exceptions_original.dart:19:3)
<asynchronous suspension>
#2 main (file:///home/work/stuff/projects/dart-async-exceptions/bin/dart_async_exceptions_original.dart:5:5)
<asynchronous suspension>
As you see it contains all invocations main -> someMethod -> someOtherMethod, that allows you to narrow down the issue. As I understand in that case we should also lose everything as we are scheduling calls on event loop. But we see everything works as expected. Why is that?
About stack_trace package: I would love to use it, but I made small experiment and looks like sometimes it provides worse trace then the one from try/catch. But that is topic for another question ;)
The short answer is that you can't trace a stack which doesn't exist.
Dart's asynchronous code is event loop based.
When you do await someFuture, your function really sets up a callback on that future, using Future.then, and then it returns. That unwinds the stack leading up to setting that callback, and eventually the stack all the way back to the event loop.
(The return only happens when you evaluate the await, the someFuture expression is invoked immediately, and if that manages to throw before doing something asynchronous, then you will get the stack trace containing the stack prior to the await returning).
At a later time, the event loop triggers and calls the callback, and the asynchronous computation continues from there.
The original stack no longer exists at that point, which is why you see a stack trace leading back to an event loop event (here, a timer, which the VM implements by sending port events at specific times). The stack you see is the only stack which exists at the point you ask for it.
You can use package:stack_trace to capture a stack trace at the point where you schedule a callback, and then the stack trace package will remember that stack trace until the callback is run, and attempt to combine it with the stack traces reported (or captured) during the callback.
Since you make lots of callbacks, but don't usually need to see that many stack traces, it has a significant performance impact to capture stacks at every callback.
I'm having trouble successfully using shareReplay from RxDart (0.24.1) in my application. I have a Stream and I would like to 'cache' the latest emitted value, so that any 'late' listeners get it immediately (the stream can be idle for longer periods). I'm failing to do this, so I started experimenting outside of my app and must admit I don't fully understand what is happening.
Here is some code:
import 'package:rxdart/rxdart.dart';
void main() async {
final s = Stream.fromIterable([1, 2, 3]).shareReplay(maxSize: 10);
print('First:');
await for (final i in s) {
print(i);
}
print('Second:');
await for (final i in s) {
print(i);
}
}
I would expect the code to print
First
1
2
3
Second
1
2
3
but it never gets to the second await for, it doesn't even print the string Second:; however, the program finishes successfully, so the first await for does finish (as the original Stream is finite). What is going on?
In reality, the Stream that I have is potentially endless with long periods of time between events), and I'm only interested in the last event, so here is some code simulating this:
import 'package:rxdart/rxdart.dart';
void main() async {
final s = Stream.periodic(Duration(seconds: 1), (e) => e).shareReplay(maxSize: 1);
// print(s.isBroadcast);
await Future.delayed(Duration(seconds: 3));
print('First');
await for (final i in s.take(1)) {
print(i);
}
print('Second');
await for (final i in s.take(1)) {
print(i);
}
}
To make sure the Stream can finish (and so await for can finish) I use take(1). I expected the output to be:
First
2
Second
2
(Maybe the twos would be threes?)
What I expected to happen is this:
The periodic stream starts emitting every second (it is broadcast/hot).
The application waits for 3 seconds due to Future.delayed.
The first late listener comes and gets the latest value, 2 (or maybe 3?) and finishes due to take(1).
The second late listener comes and gets the latest value as well because the stream didn't emit anything else in the meantime (even if it does, the value would be greater by 1, which is Ok) and finishes due to take(1).
The app finishes.
However, the output is:
First
0
Second
Unhandled exception:
type '_TakeStream<int>' is not a subtype of type 'Future<bool>'
#0 _StreamIterator._onData (dart:async/stream_impl.dart:1067:19)
#1 _RootZone.runUnaryGuarded (dart:async/zone.dart:1384:10)
#2 _BufferingStreamSubscription._sendData (dart:async/stream_impl.dart:357:11)
#3 _BufferingStreamSubscription._add (dart:async/stream_impl.dart:285:7)
#4 _ForwardingStreamSubscription._add (dart:async/stream_pipe.dart:127:11)
#5 _TakeStream._handleData (dart:async/stream_pipe.dart:318:12)
#6 _ForwardingStreamSubscription._handleData (dart:async/stream_pipe.dart:157:13)
#7 _RootZone.runUnaryGuarded (dart:async/zone.dart:1384:10)
#8 _BufferingStreamSubscription._sendData (dart:async/stream_impl.dart:357:11)
#9 _BufferingStreamSubscription._add (dart:async/stream_impl.dart:285:7)
#10 _SyncBroadcastStreamController._sendData (dart:async/broadcast_stream_controller.dart:385:25)
#11 _BroadcastStreamController.add (dart:async/broadcast_stream_controller.dart:250:5)
#12 _StartWithStreamSink._safeAddFirstEvent (package:rxdart/src/transformers/start_with.dart:56:12)
#13 _StartWithStreamSink.onListen (package:rxdart/src/transformers/start_with.dart:37:11)
#14 forwardStream.<anonymous closure>.<anonymous closure> (package:rxdart/src/utils/forwarding_stream.dart:31:37)
#15 forwardStream.runCatching (package:rxdart/src/utils/forwarding_stream.dart:24:12)
#16 forwardStream.<anonymous closure> (package:rxdart/src/utils/forwarding_stream.dart:31:16)
#17 _runGuarded (dart:async/stream_controller.dart:847:24)
#18 _BroadcastStreamController._subscribe (dart:async/broadcast_stream_controller.dart:213:7)
#19 _ControllerStream._createSubscription (dart:async/stream_controller.dart:860:19)
#20 _StreamImpl.listen (dart:async/stream_impl.dart:493:9)
#21 DeferStream.listen (package:rxdart/src/streams/defer.dart:37:18)
#22 StreamView.listen (dart:async/stream.dart:1871:20)
#23 new _ForwardingStreamSubscription (dart:async/stream_pipe.dart:118:10)
#24 new _StateStreamSubscription (dart:async/stream_pipe.dart:341:9)
#25 _TakeStream._createSubscription (dart:async/stream_pipe.dart:310:16)
#26 _ForwardingStream.listen (dart:async/stream_pipe.dart:83:12)
#27 _StreamIterator._initializeOrDone (dart:async/stream_impl.dart:1041:30)
#28 _StreamIterator.moveNext (dart:async/stream_impl.dart:1028:12)
#29 main (package:shopping_list/main.dart)
<asynchronous suspension>
#30 _startIsolate.<anonymous closure> (dart:isolate-patch/isolate_patch.dart:301:19)
#31 _RawReceivePortImpl._handleMessage (dart:isolate-patch/isolate_patch.dart:168:12)
The first await for with take(1) to actually make it finish works as I would expect it to, with the exception that it gets the the initial value, which means the stream didn't stat emitting anything before the listener came (is not 'hot'). The second fails with an exception. What am I missing?
EDIT: my understanding of shareReplay may have been wrong all along, I though it is hot because of https://pub.dev/documentation/rxdart/latest/rx/ReplaySubject-class.html says it is hot.
I changed the code a bit:
import 'package:rxdart/rxdart.dart';
void main() async {
final s = BehaviorSubject();
s.addStream(Stream.periodic(Duration(seconds: 1), (e) => e));
// print(s.isBroadcast);
await Future.delayed(Duration(seconds: 3));
print('First');
await for (final i in s.take(1)) {
print(i);
}
print('Second');
await for (final i in s.take(1)) {
print(i);
}
}
and now the output is:
First
2
Second
2
BUT the program never finishes...
Without take(1) the output never gets to the second listener, so it does have some effect. I don't get it.
EDIT 2: I think I might know why the first example with shareReplay doesn't work, here is an excerpt from the docs:
It will automatically begin emitting items when first listened to, and shut down when no listeners remain.
In my case, the first listener/await for subscribes, and the stream starts, and when the loop is done the last (and only) listener is finished, so the stream returned from shareReplay shuts down. Still doesn't explain why the line print('Second'); doesn't execute, though.
The reason your final program doesn't terminate is that your broadcast stream is still emitting events every second.
Nobody's listening, but it's a broadcast stream so it doesn't care. It has a timer ticking every second, and that timer keeps the program alive, even if nobody is ever going to listen again.
You can keep your program alive by doing Timer.periodic(Duration(seconds: 1), (_) {}); as well. As long as the timer is live, something might happen.
The crash is interesting, though. It suggests a problem with the internal logic of the StreamIterator class. I'll look into that.
Can't say anything guaranteed useful about shareReplay, I'm not familiar with RxDart.
My guess is that the first program gets into a problem because the replayShared stream doesn't terminate properly - that is, doesn't send a done event when it's done. That would explain the program terminating early. The first await for is waiting for the next event, so it doesn't end and go to the next loop, but there are no live timers or scheduled events of any kind left, so the isolate just shuts down.
A quick read of BeheaviorSubject suggests that it works like a stream controller, so you probably need to close it after the addStream has completed. Maybe:
s.addStream(...).whenComplete(s.close);
I'm seeing unexpected breaks in to the debugger in Xcode, related to the svc #128 ARM instruction from a call to pthread_kill to signal another thread. I've seen this for a number of StackOverflow questions related to this issue on iOS - but they weren't helpful for me. In this case, doing Debug->Continue (^⌘Y) repeatedly resolves the problem and execution continues without any apparent side effects. Also, if it's run outside of the debugger, then the app works fine. My goal is to understand why this is happening and avoid breaking in to the debugger except when intended.
Is there an Xcode setting that I might have accidentally set that breaks on these signals?
I'm using Google's Java to Objective-C Transpiler (j2objc), though other iOS devs have mentioned this issue unrelated to j2objc, so I don't believe that's the cause. It occurs when the j2objc Java Runtime Environment Emulation project is signaling other blocked threads. It consistently has 3 threads to signal. After doing Debug->Continue three times, then the program execution carries on without issue or apparent side effect. There are no breakpoints in the project.
The app spawns another thread at startup that uses the Java DatagramSocket class. The Java code works correctly. The transpiled Objective-C code also works correctly except for the annoying breaks in to the debugger.
This is the Stack Frame at interrupt:
main (1)Queue : com.apple.main-thread (serial)
#0 0x0000000195557270 in __pthread_kill ()
#1 0x00000001955f5228 in pthread_kill ()
// Java Runtime Environment Emulation
#2 0x00000001002f7898 in +[AsynchronousSocketCloseMonitor signalBlockedThreads:] ()
#3 0x00000001002f9754 in LibcoreIoIoBridge_closeSocketWithJavaIoFileDescriptor_ ()
#4 0x00000001001f4894 in -[JavaNetPlainDatagramSocketImpl close] ()
// My Code
#5 0x000000010016db88 in <my code>...
Local assembly in kernel pthread_kill method...
libsystem_kernel.dylib`__pthread_kill:
0x195557268: movz x16, #328
0x19555726c: svc #128
// The debugger lands on the following line but I think svc #128 is the cause
0x195557270: b.cc 0x195557288 ; __pthread_kill + 32
0x195557274: stp fp, lr, [sp, #-16]!
0x195557278: mov fp, sp
0x19555727c: bl 0x19553e59c ; cerror_nocancel
0x195557280: mov sp, fp
0x195557284: ldp fp, lr, [sp], #16
0x195557288: ret
The closest non-kernel function in the stack frame is signalBlockedThreads. When my code closes the socket, signalBlockedThreads iterates through all the threads, looking for those blocked against a specific file descriptor (I presume this corresponds to the port number that was just closed). For those relevant blocked threads, they're each signaled with pthread_kill. The method code is copied below.
For the file link, even though this is a Java file, it has embedded Objective-C code that is preserved by the j2objc transpiler:
https://github.com/google/j2objc/blob/765354b620b2c0248945b27062209620d4cf5e40/jre_emul/android/libcore/luni/src/main/java/libcore/io/AsynchronousCloseMonitor.java#L89
+ (void)signalBlockedThreads:(int)fd {
pthread_mutex_lock(&blockedThreadListMutex);
for (AsynchronousSocketCloseMonitor* it = blockedThreadList; it != NULL; it = it->mNext) {
if (it->mFd == fd) {
// MY ADDED COMMENT: BLOCKED_THREAD_SIGNAL == SIGUSR2 in this code
pthread_kill(it->mThread, BLOCKED_THREAD_SIGNAL);
// Keep going, because there may be more than one thread...
}
}
pthread_mutex_unlock(&blockedThreadListMutex);
}
Debug attempts without success:
* Add and remove "All Exceptions" breakpoint - nothing revealed by this
* Remove closeSocket call - averts issue but obviously not a solution to leave socket open
There's a trick to asking Xcode to ignore the signals. I'm curious as to why Xcode is configured by default to interrupt on signals but there you go. Note that the method varies according to the language that you're using - I've edited it to extend the example to Swift:
Permanently configuring LLDB (in Xcode 4.3.2) not to stop on signals
I have an application that makes heavy use of audio. I use AVAudioPlayers to simplify the task.
I've noticed crashes from time to time when using the players, usually when I call [player play]. The stack trace looks something like this:
EXC_BAD_ACCESS
#0 0x32d531e6 in memmove$VARIANT$CortexA8 ()
#1 0x351056dc in Cached_DataSource::ReadFromHeaderCache ()
#2 0x351052a4 in Cached_DataSource::ReadBytes ()
#3 0x350ba47c in AudioFileObject::ReadBytes ()
#4 0x35104562 in AudioFileObject::ReadPacketDataVBR ()
#5 0x35102c70 in AudioFileObject::ReadPacketData ()
#6 0x351020b2 in AudioFileReadPacketData ()
#7 0x36bad1b8 in AudioPlayerAQOutputCallbackCore ()
#8 0x36bad7a4 in prepareToPlayQueue ()
#9 0x36bad954 in playQueue ()
#10 0x36bac27e in -[AVAudioPlayer play] ()
I have breakpoints set up in every dealloc call, so I know that I'm not inadvertently dealloc-ing a player or delegate or similar.
The players are sometimes stopped before they play their full sound, so I always make a [player setCurrentTime:0] call before playing. I'm not sure if this could cause some negative side effects.
Clearly the audio queue is trying to access invalid memory, but from the looks of things that memory lives way down in the file cache code, so I can't see how anything I'm doing would affect it. All of the files I'm playing are included as resources in the main bundle.
I created a repro that reliably reproduces this in the 4.1 simulator and on my 5.0.1 device. It can take a little while and hundreds of calls to setCurrentTime, play, and stop before it crashes.
I need to get to the bottom of this. I can start porting all of my code to use audio queues or something else if required, but I want to make sure that there isn't something I'm missing or that I could do differently to make this more stable.
I am getting the following index out of bounds error:
*** Terminating app due to uncaught exception 'NSRangeException', reason:
'*** -[__NSArrayM objectAtIndex:]: index 0 beyond bounds for empty array'
*** First throw call stack:
(0x2263052 0x24c7d0a 0x224fdb8 0x2f4a7 0x2264ec9 0x81e299 0x81e306 0x75aa30
0x75ac56 0x741384 0x734aa9 0x39a9fa9 0x22371c5 0x219c022 0x219a90a 0x2199db4
0x2199ccb 0x39a8879 0x39a893e 0x732a9b 0x1e5b 0x1dc5 0x1)
I know exactly what the error means, but I find these errors very difficult to fix because for some reason the call stack isn't telling me the line of code where the array was being called. Here is the call stack from thread 1:
#0 0x9706d9c6 in __pthread_kill ()
#1 0x93e2cf78 in pthread_kill ()
#2 0x93e1dbdd in abort ()
#3 0x02859e78 in dyld_stub__Unwind_DeleteException ()
#4 0x0285789e in default_terminate() ()
#5 0x024c7f4b in _objc_terminate ()
#6 0x028578de in safe_handler_caller(void (*)()) ()
#7 0x02857946 in __cxa_bad_typeid ()
#8 0x02858b3e in __cxa_current_exception_type ()
#9 0x024c7e49 in objc_exception_rethrow ()
#10 0x02199e10 in CFRunLoopRunSpecific ()
#11 0x02199ccb in CFRunLoopRunInMode ()
#12 0x039a8879 in GSEventRunModal ()
#13 0x039a893e in GSEventRun ()
#14 0x00732a9b in UIApplicationMain ()
#15 0x00001e5b in main
As you can see this call stack is not very helpful because it doesn't show any methods from my code. Also, the call stack shown in the error has 22 memory addresses, while the stack from thread 1 only has 15, and the addresses don't match at all. No other threads seem to contain any useful information.
How is it possible to see the thread of the "First throw call stack" from the error (the one with 22 addresses), so I can find the line causing this error? Perhaps I have something set incorrectly in my Build Settings that is causing the relevant stack to not be retrievable?
If someone could point me in the right direction on this I'd be very grateful. Trying to locate the offending line manually is quite tedious.
Thanks!
turn on the debugger and set a breakpoint on whenever an exception is thrown, this way you exactly know which line of code is being a jerk.
objc_exception_throw
Alternatively, [NSException raise];
Have a look at the following question: Add breakpoint to objc-exception-throw
Did you enable global breakpoints in your project?
if not add objc_exception_throw to the breakpoints section in the project navigator then re-run the app, you should get the stack. In adition, when you crash happends, watch and expand any additional threads to see their stacks as well. It happened to me several times that the stack i was searching was in a background thread, though the crash was being reported by the main thread. HTH.
Assuming this happened while in the XCode debugger, you can determine
the line of code referenced in the traceback addresses.
In the debug window, enter the following:
list *address from traceback
For example, for your first entry, you would enter the following:
list *0x2263052
Do this for each address. One of them should point to your programs code
and list the failing line number and code above and below the failing line.
-Steve