Why "dict[String(aUint16)] = Int(Date().timeIntervalSince1970 * 1000)" failed in some cases? [duplicate] - ios

This question already has an answer here:
Timestamp function that has been working reliably just caused EXC_BAD_INSTRUCTION
(1 answer)
Closed 5 years ago.
My code, which use SimplePing:
func simplePing(_ pinger: SimplePing, didSendPacket packet: Data, sequenceNumber: UInt16) {
begin[String(sequenceNumber)] = Int(Date().timeIntervalSince1970 * 1000)//AppDelegate.swift:185
print("Send: \(Common.startCount)")
}
It works perfectly in my simulator and iPhone, but after made it available on AppStore, I received about 20 crash logs with some error like that:
Exception Type: EXC_BREAKPOINT (SIGTRAP)
Exception Codes: 0x0000000000000001, 0x00000000e7ffdefe
Triggered by Thread: 1
...
Thread 1 name:
Thread 1 Crashed:
0 ME 0x0011e5cc specialized AppDelegate.simplePing(SimplePing, didSendPacket : Data, sequenceNumber : UInt16) -> () + 652 (AppDelegate.swift:185)
1 ME 0x00116990 #objc AppDelegate.simplePing(SimplePing, didSendPacket : Data, sequenceNumber : UInt16) -> () + 68
2 ME 0x00116818 #objc AppDelegate.simplePing(SimplePing, didSendPacket : Data, sequenceNumber : UInt16) -> () + 40
3 ME 0x000f3348 -[SimplePing sendPingWithData:] + 640 (SimplePing.m:297)
...
I can't reproduce that crash, so I have to analysis that line of the code:
begin[String(sequenceNumber)]
begin initialized with begin = [String: Int](), so its type is [String : Int], and sequenceNumber's type is UInt16. So I think begin[String(sequenceNumber)] doesn't have any potential bug.
Int(Date().timeIntervalSince1970 * 1000)
And Int(Date().timeIntervalSince1970 * 1000) is just something like Int(aDouble * 1000), it seems correct in any situation.
So I get really confused with that crash log, could anyone please give me some hints?

From the docs for Int:
On 32-bit platforms, Int is the same size as Int32, and on 64-bit platforms, Int is the same size as Int64.
A signed 32-bit integer has a maximum value of 2,147,483,647.
At the moment, Int(Date().timeIntervalSince1970 * 1000) returns a value of 1,495,855,170,970.
That is significantly larger than what will fit in a 32-bit integer.
The crash is being caused by the overflow you are attempting when casting the Double to an Int when run on a 32-bit iOS device.
I would suggest an explicit use of Int64 instead of Int:
begin[String(sequenceNumber)] = Int64(Date().timeIntervalSince1970 * 1000)

Related

Swift framework with a C lib inside: Got segmentation fault during working with C types

I'm building swift wrapper for PJSIP C lib.
I faced with a strange behaviour of memory alloc/free.
This func produces seg fault error [old plain NULL pointer]:
pjsua_msg_data is a C struct
static func makePj(fromHeaders headers: [SipHeader],
pool: inout UnsafeMutablePointer<pj_pool_t>) -> pjsua_msg_data {
var msgData = pjsua_msg_data()
pjsua_msg_data_init(&msgData)
pj_list_init(&msgData.hdr_list)
for header in headers {
let pjHeader = header.toPj(pool: &pool)
pj_list_push_back(&msgData.hdr_list, pjHeader)
}
return msgData
}
This implementation works (difference is that msgData as inout param)
static func makePj(fromHeaders headers: [SipHeader],
msgData: inout pjsua_msg_data,
pool: inout UnsafeMutablePointer<pj_pool_t>) {
pjsua_msg_data_init(&msgData)
pj_list_init(&msgData.hdr_list)
for header in headers {
let pjHeader = header.toPj(pool: &pool)
pj_list_push_back(&msgData.hdr_list, pjHeader)
}
}
Usage
var msgData = pjsua_msg_data()
var pool = try API.shared.createMemPool("pool", block: 4096, increment: 1024)
defer { try? API.shared.releaseMemPool(pool) }
if !headers.isEmpty {
// - usage of working implementations
//MessageData.makePj(fromHeaders: headers,
// msgData: &msgData,
// pool: &pool)
// - seg fault implementation usage
msgData = MessageData.makePj(fromHeaders: headers,
pool: &pool)
}
try callPJSUA {
pjsua_call_make_call(accountId,
&uriStr,
&callSetting,
nil,
&msgData,
&callId)
}
Little bit about framework:
it's a just Swift wrapper under C lib.
This framework then linked to the iOS app
Question:
I don't understand why inout param works but returning value doesn't.
Can I change this swift compiler behaviour? Build settings or smth else ?
Exception:
Exception Type: EXC_BAD_ACCESS (SIGSEGV)
Exception Subtype: KERN_INVALID_ADDRESS at 0x0000000000000000
Exception Codes: 0x0000000000000001, 0x0000000000000000
VM Region Info: 0 is not in any region. Bytes before following region: 4365074432
REGION TYPE START - END [ VSIZE] PRT/MAX SHRMOD REGION DETAIL
UNUSED SPACE AT START
--->
__TEXT 1042dc000-1056ec000 [ 20.1M] r-x/r-x SM=COW ...app/CallScape
Exception Note: EXC_CORPSE_NOTIFY
Termination Reason: SIGNAL 11 Segmentation fault: 11
Terminating Process: exc handler [2095]
Thread 11 name: Dispatch queue: working.queue
Thread 11 Crashed:
0 SDK 0x10d3f3f28 pjsip_hdr_clone + 36
1 SDK 0x10d6d7454 pjsua_msg_data_clone + 280
2 SDK 0x10d6d7454 pjsua_msg_data_clone + 280
3 SDK 0x10d6cc4c8 pjsua_call_make_call + 1276
4 SDK 0x10d38a710 specialized CallAPI.make(_:destinationURI:setting:headers:) + 1268
5 SDK 0x10d389de8 protocol witness for CallAPI.make(_:destinationURI:setting:headers:) in conformance API + 12
6 SDK 0x10d39c8a8 Call.make(to:setting:headers:) + 152

Why does app crash at NSData getBytes?

NSData is extended to determine the file type:
extension NSData {
var dataType: String? {
// Ensure data length is at least 1 byte
guard self.length > 0 else { return nil }
// Get first byte
var c = [UInt8](count: 1, repeatedValue: 0)
self.getBytes(&c, length: 1)
// Identify data type
switch (c[0]) {
case 0xFF:
return "jpg"
case 0x89:
return "png"
case 0x47:
return "gif"
case 0x49, 0x4D:
return "tiff"
default:
return nil //unknown
}
}
}
The method above is called on a NSData object from image data that is fetched from a server.
dispatch_async(dispatch_get_global_queue(QOS_CLASS_BACKGROUND, 0)) {
do {
// Fetch image synchronously from server
let query = PFQuery(className: <...>)
let result = try query.getFirstObject()
guard
let imageObject = result.objectForKey(<...>) as? PFFile,
let imageData = try? imageObject.getData(),
let image = imageData.dataType == "gif" ? UIImage.animatedImageWithAnimatedGIFData(imageData) : UIImage(data: imageData)
else {
return
}
<...>
} catch (let error as NSError) {
<...>
}
}
However the app very rarely crashes at line self.getBytes:
What is the reason for this?
The buffer of getBytes is &c, an UnsafeMutablePointer - do I have to take any special memory considerations because of that?
Update
The crashes still occur with the following variation of the code:
// Get first byte
var c: UInt8 = 0;
self.getBytes(&c, length: 1)
Update
The crashes still occur with the following variation of the code:
// Get first byte
var c = [UInt8](count: 1, repeatedValue: 0)
c.withUnsafeMutableBufferPointer {
buffer in
getBytes(buffer.baseAddress, length: 1)
}
guard c.indices.contains(0) else { return nil }
I got the following crash and included the whole thread, maybe someone can spot a hint:
Thread 18 Crashed:
0 libsystem_platform.dylib 0x21a8e198 _platform_memmove$VARIANT$CortexA9 + 92
1 Foundation 0x22512923 __34-[_NSDispatchData getBytes:range:]_block_invoke + 176
2 libdispatch.dylib 0x218d238d _dispatch_data_apply + 82
3 libdispatch.dylib 0x218d4a51 dispatch_data_apply + 26
4 Foundation 0x22512865 -[_NSDispatchData getBytes:range:] + 86
5 Foundation 0x2267730b -[_NSDispatchData getBytes:length:] + 24
6 MyAppName 0x00079ba0 partial apply forwarder for (extension in MyAppName):__ObjC.NSData.(dataType.getter : Swift.String?).(closure #1) (NSData+Extension.swift:54)
7 MyAppName 0x00079c14 partial apply forwarder for reabstraction thunk helper from #callee_owned (#inout Swift.UnsafeMutableBufferPointer<Swift.UInt8>) -> (#unowned (), #error #owned Swift.ErrorType) to #callee_owned (#inout Swift.UnsafeMutableBufferPointer<Swift.UInt8>) -> (#out (), #error #owned Swift.ErrorType) (NSData+Extension.swift:0)
8 MyAppName 0x00079cb8 generic specialization <Swift.UInt8, ()> of Swift.Array.withUnsafeMutableBufferPointer <A> ((inout Swift.UnsafeMutableBufferPointer<A>) throws -> A1) throws -> A1 (NSData+Extension.swift:0)
9 MyAppName 0x00079a70 (extension in MyAppName):__ObjC.NSData.dataType.getter : Swift.String? (NSData+Extension.swift:55)
10 MyAppName 0x00079948 #objc (extension in MyAppName):__ObjC.NSData.dataType.getter : Swift.String? (NSData+Extension.swift:0)
11 MyAppName 0x000d2264 MyAppName.DataManager.(fetchImagesFromServer (MyAppName.ImageSet) -> ()).(closure #1) (DataManager.swift:1214)
12 libdispatch.dylib 0x218cd823 _dispatch_call_block_and_release + 8
13 libdispatch.dylib 0x218dc5e9 _dispatch_root_queue_drain + 1558
14 libdispatch.dylib 0x218dbfcd _dispatch_worker_thread3 + 94
15 libsystem_pthread.dylib 0x21a91b29 _pthread_wqthread + 1022
16 libsystem_pthread.dylib 0x21a91718 start_wqthread + 6
Update
The crashes still occur with the following variation of the code:
// Get first byte
var c = UnsafeMutablePointer<UInt8>.alloc(1)
defer { c.dealloc(1) }
self.getBytes(c, length: 1)
switch (c[0]) { ...
With the help of an Apple engineer (via a TSI ticket) the issue was finally identified.
All code permutations above for reading the first byte are valid and working.
The issue was that the NSData object was created when a file was fetched from a server using the Parse iOS SDK which stores the data in a temporary file with file protection key NSFileProtectionCompleteUntilFirstUserAuthentication.
The file protection key allows reading data of the NSData object only after the user unlocks the device once after reboot. Although the data is not readable before unlocking, the NSData object can be created and even the NSData.length property is accessible. However, attempting to read the data would throw an exception.
I changed the code and added a check if the protected data is available before attempting to read it with UIApplication.sharedApplication().protectedDataAvailable.
You may wonder why a file was fetched by the app before the device was even unlocked. The app was started by a remote user notification. That explains why the crash happened so rarely.
Learned 2 things:
Always check your file protection key
Apple technical support gave a super in-depth explanation and is worth the money
A Swift array is more like a C++ std::vector than a C array: it has other contents besides the array elements. You can't get a pointer to the first element using &c. You need to ask the array for a pointer to its elements, like this:
var c = [UInt8](count: 1, repeatedValue: 0)
c.withUnsafeMutableBufferPointer { buffer in
getBytes(buffer.baseAddress, length: 1)
}
For your particular case, it seems overkill to use an array, though. Why not just do:
var c: UInt8 = 0;
self.getBytes(&c, length: 1)

SIGBUS crash on Solaris 8

Compiled with g++ 4.7.4 on Solaris 8. 32 bit application. Stack trace is
Core was generated by `./z3'.
Program terminated with signal 10, Bus error.
\#0 0x012656ec in vector<unsigned long long, false, unsigned int>::push_back (this=0x2336ef4 <g_prime_generator>, elem=#0xffbff1f0: 2) at ../src/util/vector.h:284
284 new (m_data + reinterpret_cast<SZ *>(m_data)[SIZE_IDX]) T(elem);
(gdb) bt
\#0 0x012656ec in vector<unsigned long long, false, unsigned int>::push_back (this=0x2336ef4 <g_prime_generator>, elem=#0xffbff1f0: 2) at ../src/util/vector.h:284
\#1 0x00ae66d4 in prime_generator::prime_generator (this=0x2336ef4 <g_prime_generator>) at ../src/util/prime_generator.cpp:24
\#2 0x00ae714c in __static_initialization_and_destruction_0 (__initialize_p=1, __priority=65535) at ../src/util/prime_generator.cpp:99
\#3 0x00ae71c4 in _GLOBAL__sub_I_prime_generator.cpp(void) () at ../src/util/prime_generator.cpp:130
\#4 0x00b16a68 in __do_global_ctors_aux ()
\#5 0x00b16aa0 in _init ()
\#6 0x00640b10 in _start ()
(gdb) list
279
280 void push_back(T const & elem) {
281 if (m_data == 0 || reinterpret_cast<SZ *>(m_data)[SIZE_IDX] == reinterpret_cast<SZ *>(m_data)[CAPACITY_IDX]) {
282 expand_vector();
283 }
284 new (m_data + reinterpret_cast\<Z *>(m_data)[SIZE_IDX]) T(elem);
285 reinterpret_cast<SZ *>(m_data)[SIZE_IDX]++;
286 }
287
288 void insert(T const & elem) {
(gdb) ptype SZ
type = unsigned int
(gdb) ptype m_data
type = unsigned long long *
SIGBUS on Solaris is usually indicative of a misaligned access, but I am not sure if it is due to the casting going on an endianess issue
The SPARC data alignment requirements is most likely at issue.
The m_data field in the vector class is off by two fields that are used
to store the size and capacity of a vector.
You can debug this by displaying (printing or using the debugger) the pointer m_data and it's alignment.
One option is to supply a separate vector implementation
where the size and capacity fields are stored
in fields directly in the vector for porting this library utility.
Z3 interacts with memory alignment a few other places (but not overly many).
The main other potential places are in the watch lists (sat_solver and smt_context), and region memory allocators (region.h) and possibly in hash tables.

Swift compiler segmentation fault with generic recursive function

I've run into an interesting issue with the Swift compiler, which seems to be caused by a very simple generic function. I've got a workaround, but I'd really like to understand what the underlying issue is.
In my app I have a requirement to fade in some UICollectionViewCells in a given order, sequentially, with a slight overlap between the animations.
I've implemented this using the methods below. The revealCells method takes an array of cells. If the collection is empty, it simply returns. Otherwise it animates the fade-in on the first cell in the array, and then waits a certain amount of time before making a recursive call to itself, passing all the cells except the one it just animated.
Code below:
func revealCells(cells:[UICollectionViewCell],animationTime:NSTimeInterval,overlap:Double) {
if cells.count > 0 {
let firstCell = cells.first
UIView.animateWithDuration(0.3, animations: { () -> Void in
firstCell?.alpha = 1.0
let timeMinusOverlap = animationTime - overlap
let delayTime = dispatch_time(DISPATCH_TIME_NOW,Int64(timeMinusOverlap * Double(NSEC_PER_SEC)))
dispatch_after(delayTime, dispatch_get_main_queue(), { () -> Void in
self.revealCells(self.cdr(cells),animationTime: animationTime,overlap: overlap)
})
})
}
}
}
//Returns the collection passed into the function with its first element removed
//i.e the traditional LISP cdr function
func cdr<T>(input:[T]) -> [T] {
var rVal = [T]()
if input.count == 1 {
rVal.append(input.first!)
} else {
rVal = [T](input[1...input.count-1])
}
return rVal
}
All this works fine in the simulator. But when I try to archive the build, the swift compiler crashes with the message Swift Compiler Error Command failed due to signal: Segmentation fault 11. My setup is Xcode 6.3.1 (iOSSDK 8.3), and my min deployment target is 8.3.
Fixing the problem is trivial - if I just replace the code inside the dispatch_after with:
let newCells = [UICollectionViewCell](cells[1...cells.count-1])
self.revealCells(newCells,animationTime: animationTime,overlap: overlap)
the problem goes away. So it seems to be something to do with the generic function, or possibly something block related.
Stack trace is:
0 swift 0x000000010105ba18 llvm::sys::PrintStackTrace(__sFILE*) + 40
1 swift 0x000000010105bef4 SignalHandler(int) + 452
2 libsystem_platform.dylib 0x00007fff8725ef1a _sigtramp + 26
3 libsystem_platform.dylib 0x000000000000000f _sigtramp + 2027557135
4 swift 0x00000001021a98cb llvm::AsmPrinter::EmitFunctionBody() + 4379
5 swift 0x000000010116c84c llvm::ARMAsmPrinter::runOnMachineFunction(llvm::MachineFunction&) + 220
6 swift 0x0000000100d81d13 llvm::MachineFunctionPass::runOnFunction(llvm::Function&) + 99
7 swift 0x00000001024d5edf llvm::FPPassManager::runOnFunction(llvm::Function&) + 495
8 swift 0x00000001024d60cb llvm::FPPassManager::runOnModule(llvm::Module&) + 43
9 swift 0x00000001024d658f llvm::legacy::PassManagerImpl::run(llvm::Module&) + 975
10 swift 0x0000000100a09b41 performIRGeneration(swift::IRGenOptions&, swift::Module*, swift::SILModule*, llvm::StringRef, llvm::LLVMContext&, swift::SourceFile*, unsigned int) + 4369
11 swift 0x0000000100a09cb3 swift::performIRGeneration(swift::IRGenOptions&, swift::SourceFile&, swift::SILModule*, llvm::StringRef, llvm::LLVMContext&, unsigned int) + 51
12 swift 0x0000000100945687 frontend_main(llvm::ArrayRef<char const*>, char const*, void*) + 6647
13 swift 0x0000000100943ae6 main + 1814
14 libdyld.dylib 0x00007fff8a46b5c9 start + 1
(a long list of program arguments, which are mostly the names of file being compiled)
1. Running pass 'Function Pass Manager' on module '/Users/tolleyr/Library/Developer/Xcode/DerivedData/ParseTestQuiz-fgnfjkxxlyqfnrfrfntgtsjnrcfv/Build/Intermediates/ArchiveIntermediates/ParseTestQuiz/IntermediateBuildFilesPath/ParseTestQuiz.build/Release-iphoneos/ParseTestQuiz.build/Objects-normal/armv7/QuizQuestionViewController.o'.
2. Running pass 'ARM Assembly / Object Emitter' on function '#_TFC13ParseTestQuiz26QuizQuestionViewController13viewDidAppearfS0_FSbT_'
(the last part enabled me to figure out what code was causing the problem). The command being run was CompileSwift normal armv7
I'm going to file a radar for this, since the compiler itself is crashing , but thought I'd post it here in case anyone has an idea of what might be going on, or has run into the same issue.

Swift: Cast from Interface type array to Object array crashes

I have got an array of objects that conform to an interface
interface SomeInterface{}
and a class that conforms to that interface
class SomeClass : NSObject, SomeInterface{}
Now, I create an array of SomeInterface objects
var myInterfaceObjects : SomeInterface[] = SomeInterface[]()
Then I would like to cast this array to a SomeClass object array
var someClassObjects : SomeClass[] = myInterfaceObjects as SomeClass[] //CRASH!
How can I downcast without a crash ?
fatal error: can't reinterpretCast values of different sizes
(lldb) bt
* thread #1: tid = 0x935ef, 0x001986b8 libswift_stdlib_core.dylib`Swift.reinterpretCast <A, B>(A) -> B + 220, queue = 'com.apple.main-thread', stop reason = EXC_BREAKPOINT (code=EXC_ARM_BREAKPOINT, subcode=0xe7ffdefe)
* frame #0: 0x001986b8 libswift_stdlib_core.dylib`Swift.reinterpretCast <A, B>(A) -> B + 220
frame #1: 0x001bebdc libswift_stdlib_core.dylib`Swift.ContiguousArrayBuffer.storesOnlyElementsOfType <A>(Swift.ContiguousArrayBuffer<A>)<B>(B.Type) -> Swift.Bool + 912
frame #2: 0x001bde08 libswift_stdlib_core.dylib`Swift._arrayCheckedDownCast <A, B>(Swift.Array<A>) -> Swift.Optional<Swift.Array<B>> + 292
frame #3: 0x00094c84 MyApp`MyApp.MyClass.(data=SomeInterface[]! at 0x27db0870, response=Foundation.NSHTTPURLResponse! at 0x27db086c, error=None, self=<unavailable>) -> (Swift.Bool) -> ()).(closure #1) + 428 at MyClass.swift:81
Sounds like a compiler bug, you should report it (as Kevin said in the comments)
For now you can try to work around it by casting the objects individually:
var someClassObjects : [SomeClass] = myInterfaceObjects.map { $0 as SomeClass }
edit: updated to the latest swift syntax. Also worth mentioning this bug may have been resolved in beta 3 or beta 4 – I haven't checked

Resources