Crash using Metal buffers - multithreading

I use a background thread to create Metal buffers:
var vertices:UnsafeMutablePointer<Float>?=nil
var indexes:UnsafeMutablePointer<UInt32>?=nil
var vertexCount: UInt32=UInt32()
var indexCount: UInt32=UInt32()
triangulatePoints(hull, &vertices, &indexes, &vertexCount, &indexCount)
defer {
free(vertices)
free(indexes)
}
if let vertexBuffer=device.makeBuffer(bytes: vertices!,
length: Int(vertexCount)*MemoryLayout<Float>.size*3,
options: .storageModeShared),
let indexBuffer=device.makeBuffer(bytes: indexes!,
length: Int(indexCount)*MemoryLayout<UInt32>.size,
options: .storageModeShared)
{
metalObject=MetalObject(vertices: vertexBuffer, indices: indexBuffer)
}
The MetalObjects are temporarily stored in a dictionary and later accumulated in arrays and the array is returned. This happens from within a dispatch queue (number #5 in the Debug stack trace below):
CustomOperationQueue.sharedInstance.addSerialOperation {
//This calls the device.makeBuffers() and stores them in a dictionary owned by the image
image.constructMetalBuffers(withPrecision: precision, device: device)
//The MetalObjects are accumulated in arrays. Sorted by their draw type, such as instanced or not. One array of each type.
let metalLayer:MetalImageLayer=image.layerWithDelegate(device: device, delegate: self)
OperationQueue.main.addOperation {
//The MTKView delegate observes this property and triggers a redraw when it changes
self.metalLayer=metalLayer
}
The MetalObjects are simple containers, which are also stored in other containers:
class MetalObject: NSObject {
var vertexBuffer: MTLBuffer
var indexBuffer: MTLBuffer
init(vertices: MTLBuffer, indices:MTLBuffer) {
vertexBuffer=vertices
indexBuffer=indices
}
}
class MetalImageLayer: NSObject {
var layers=[MetalPolarityLayer]()
}
class MetalPolarityLayer: NSObject {
var elements=[MetalObject]() //For general objects that need to be drawn piece by piece
var regions=[MetalObject]() //For region objects that can be instanced
}
In Debug mode, I often get crashes on the line metalObject=MetalObject(vertices: vertexBuffer, indices: indexBuffer) with a EXC_BAD_ACCESS (code=1, address=0x40dedeadbec8). The stack trace looks like:
#0 0x000000010166a6e2 in swift_unknownRetain ()
#1 0x000000010005bf5f in StrokeLine.constructMetalBuffers(withPrecision:device:) at Image+Metal.swift:445
#2 0x000000010005c8b2 in #objc StrokeLine.constructMetalBuffers(withPrecision:device:) ()
#3 0x0000000100050b4d in Image.constructMetalBuffers(withPrecision:device:) at Image+Metal.swift:40
#4 0x0000000100051082 in #objc Image.constructMetalBuffers(withPrecision:device:) ()
#5 0x0000000100067eef in closure #1 in WindowLayer.observeValue(forKeyPath:of:change:context:) at WindowLayer.swift:181
Inspecting the vertexBuffer from the debugger then gives: po vertexBuffer
error: Execution was interrupted, reason: EXC_BAD_ACCESS (code=1, address=0x2e7466697770).
On the other hand in Release mode, I sometimes get crashes on
Crashed Thread: 0 Dispatch queue: com.apple.main-thread
Exception Type: EXC_CRASH (SIGABRT)
Exception Codes: 0x0000000000000000, 0x0000000000000000
Exception Note: EXC_CORPSE_NOTIFY
Application Specific Information:
abort() called
Thread 0 Crashed:: Dispatch queue: com.apple.main-thread
0 libsystem_kernel.dylib 0x00007fff60084fce __pthread_kill + 10
1 libsystem_pthread.dylib 0x00007fff601c2150 pthread_kill + 333
2 libsystem_c.dylib 0x00007fff5ffe132a abort + 127
3 com.apple.IOAccelerator 0x00007fff5279a1ea ioAccelResourceListAddNewGroupAndResource + 221
4 com.apple.IOAccelerator 0x00007fff52799d19 IOAccelResourceListAddResource + 304
5 com.apple.driver.AppleIntelKBLGraphicsMTLDriver 0x00007fff32aa02ef IGBufferMemory<31ul>::listId(unsigned int) + 85
6 com.apple.driver.AppleIntelKBLGraphicsMTLDriver 0x00007fff32aa654b ShaderBindingStage::updateUAVTable(unsigned int, unsigned int, bool) + 459
7 com.apple.driver.AppleIntelKBLGraphicsMTLDriver 0x00007fff32a9fe0d ShaderBindingStage::updateBindingTableData() + 1631
8 com.apple.driver.AppleIntelKBLGraphicsMTLDriver 0x00007fff32a9f70b ShaderBindingStage::writeTableIf() + 55
9 com.apple.driver.AppleIntelKBLGraphicsMTLDriver 0x00007fff32a9cc11 IGAccelRenderCommandEncoder::programPipeline(sPrimitiveData const&) + 4685
10 com.apple.driver.AppleIntelKBLGraphicsMTLDriver 0x00007fff32a9b7b4 IGAccelRenderCommandEncoder::drawIndexedPrimitives(MTLPrimitiveType, unsigned int, MTLIndexType, MTLIGAccelBuffer*, unsigned int, unsigned int, unsigned int, unsigned int) + 710
11 com.apple.driver.AppleIntelKBLGraphicsMTLDriver 0x00007fff32a9b40c -[MTLIGAccelRenderCommandEncoder drawIndexedPrimitives:indexCount:indexType:indexBuffer:indexBufferOffset:] + 324
No further information is logged about what might cause the crash.
Using Instruments to find Zombies gives no results.
How should I go about finding out what goes wrong here?

Related

After reboot, on resumption of uncompression, inflate() is reporting Z_DATA_ERROR

Thanks Mark, on resumption, now I get Z_DATA_ERROR
case STORED:
strm->msg = (char *)"invalid stored block lengths"; // got here - Anton
state->mode = BAD;
Just to see I understood your suggestions yesterday:
after inflateInit2()
// go to byte offset
ZSEEK64( , , streamCurrentPos, ZLIB_FILEFUNC_SEEK_SET)
if ( streamBits > 0 )
{
// get that byte
unz64local_getByte( , , &aByte)
// and shift down by the number of bits. This API doing it?
inflatePrime ( , streamBits, 8 - streamBits)
} else { no bits to insert }
inflateSetDictionary ()
And state of uncompression is saved like this:
typedef struct state_of_uncompression
{
ZPOS64_T streamCurrentPos; // from : unzGetCurrentFileZStreamPos64()
int streamBits; // from : stream.data_type & (~0x1C0), after clearing bits 8,7, and 6
Byte dictionary_buf[32768]; // from : inflateGetDictionary()
uInt dictLength; // from : inflateGetDictionary();
uint64_t output_wrt_offset // got this already.
} uncompression_state_info;
What? No.
inflatePrime ( , streamBits, 8 - streamBits) makes no sense. And you did nothing with the aByte you got.
It should be inflatePrime(strm, streamBits, aByte >> (8 - streamBits)).

libMobileGestalt.dylib crashed when Hooking MGCopyAnswer for ARM64

When I try to hook MGCopyAnswer, I get a crash. I'm trying this on a jailbroken iPhone 5s in iOS 8.3, arm64 binaries.
#import <substrate.h>
extern "C" CFTypeRef MGCopyAnswer(CFStringRef);
MSHook(CFTypeRef, MGCopyAnswer, CFStringRef key)
{
  return _MGCopyAnswer(key);
}
%ctor
{
  NSString *appID = [[NSBundle mainBundle] bundleIdentifier];
  if ( appID && [appID isEqualToString:#"com.test.test"])   {
    MSHookFunction(MGCopyAnswer, MSHake(MGCopyAnswer));
  }
}
Makefile:
ARCHS = armv7 armv7s arm64
TARGET = iphone:latest:8.0
test2_FRAMEWORKS = UIKit
include theos/makefiles/common.mk
TWEAK_NAME = test2
test2_FILES = Tweak.xm
test2_LIBRARIES = MobileGestalt
include $(THEOS_MAKE_PATH)/tweak.mk
after-install::
  install.exec "killall -9 SpringBoard"
Crash log:
Version: 1.44 (1.4)
Code Type: ARM-64 (Native)
Parent Process: launchd [1]
Date/Time:           2016-04-25 01:09:31.810 +0800
Launch Time:         2016-04-25 01:09:31.564 +0800
OS Version:          iOS 8.3 (12F70)
Report Version:      105
Exception Type:  EXC_BAD_INSTRUCTION (SIGILL)
Exception Codes: 0x0000000000000001, 0x000000000068fe68
Triggered by Thread:  0
Thread 0 name:  Dispatch queue: com.apple.main-thread
Thread 0 Crashed:
0   libMobileGestalt.dylib          0x0000000195af7e84 0x195af4000 + 16004
1   libMobileGestalt.dylib          0x0000000195af82bc MGGetBoolAnswer + 32
2   AppSupport                      0x000000018b020594 __CPIsInternalDevice_block_invoke + 16
3   libdispatch.dylib               0x0000000196c99950 _dispatch_client_callout + 12
4   libdispatch.dylib               0x0000000196c9a828 dispatch_once_f + 92
5   AppSupport                      0x000000018b02057c CPIsInternalDevice + 60
6   UIKit                           0x0000000189b58750 ___UIApplicationUsesAlternateUI_block_invoke + 12
7   libdispatch.dylib               0x0000000196c99950 _dispatch_client_callout + 12
8   libdispatch.dylib               0x0000000196c9a828 dispatch_once_f + 92
9   UIKit                           0x0000000189923750 UIApplicationInitialize + 1872
10  UIKit                           0x0000000189922b1c UIApplicationMain + 320
MGCopyAnswer:
->  0x193a7fe84 <+0>:  .long  0x002d7c28                ; unknown opcode
    0x193a7fe88 <+4>:  .long  0x00000001                ; unknown opcode
    0x193a7fe8c <+8>:  stp    x20, x19, [sp, #32]
    0x193a7fe90 <+12>: stp    x29, x30, [sp, #48]
    0x193a7fe94 <+16>: add    x29, sp, #48
    0x193a7fe98 <+20>: sub    sp, sp, #48
    0x193a7fe9c <+24>: mov    x19, x1
    0x193a7fea0 <+28>: mov    x22, x0
    0x193a7fea4 <+32>: movz   w0, #0
    0x193a7fea8 <+36>: bl     0x193a7f564               ; ___lldb_unnamed_function54$$libMobileGestalt.dylib
    0x193a7feac <+40>: orr    w1, wzr, #0x1
    0x193a7feb0 <+44>: mov    x0, x22
    0x193a7feb4 <+48>: bl     0x193a7f5fc               ; ___lldb_unnamed_function56$$libMobileGestalt.dylib
    0x193a7feb8 <+52>: mov    x21, x0
    0x193a7febc <+56>: movz   w20, #0
    0x193a7fec0 <+60>: cbz    x21, 0x193a7fefc          ; <+120>
    0x193a7fec4 <+64>: ldr    w20, [x21, #148]
    0x193a7fec8 <+68>: mov    x0, x21
orig_MGCopyAnswer
    0x104234000: movz   x1, #0
    0x104234004: stp    x24, x23, [sp, #-64]!
    0x104234008: stp    x22, x21, [sp, #16]
    0x10423400c: ldr    x16, #8
    0x104234010: br     x16
    0x104234014: .long  0x93a7fe8c                
    0x104234018: .long  0x00000001                ; unknown opcode
What am I doing wrong?
You cannot hook MGCopyAnswer directly because it is too short.
When CydiaSubstrate hooks a C function, it sorts of overwrites an assembly version of goto your_function; at the beginning of the original function. This "goto" in ARM64 is 16 bytes in size, which means if the original function is too short (< 16 bytes), CydiaSubstrate can spill over and corrupt the neighboring functions.
This is exactly why the problem of MGCopyAnswer. The implementation of MGCopyAnswer is basically (on 9.3.2 arm64):
01 00 80 d2 movz x1, #0
01 00 00 14 b MGCopyAnswer_internal
which is just 8 bytes (< 16 bytes) in size. So CydiaSubstrate will corrupt the 8 bytes after the end of MGCopyAnswer.
Unfortunately, MGCopyAnswer_internal is right after MGCopyAnswer, and even worse this function and is called by MGGetBoolAnswer as well. Since MGCopyAnswer_internal is corrupt, you get an EXC_BAD_INSTRUCTION crash inside libMobileGestalt.
A good news for MGCopyAnswer is that, you could just hook MGCopyAnswer_internal! This has an additional benefit that many related functions like MGGetBoolAnswer, MGCopyAnswerWithError, MGCopyMultipleAnswers etc. can respond to your change as well. The bad thing is that MGCopyAnswer_internal is completely internal, and there is no symbols pointing to it. We could rely on the fact that MGCopyAnswer_internal is exactly 8 bytes after MGCopyAnswer on ARM64, and develop this ugly hack:
static CFPropertyListRef (*orig_MGCopyAnswer_internal)(CFStringRef prop, uint32_t* outTypeCode);
CFPropertyListRef new_MGCopyAnswer_internal(CFStringRef prop, uint32_t* outTypeCode) {
return orig_MGCopyAnswer_internal(prop, outTypeCode);
}
extern "C" MGCopyAnswer(CFStringRef prop);
static CFPropertyListRef (*orig_MGCopyAnswer)(CFStringRef prop);
CFPropertyListRef new_MGCopyAnswer(CFStringRef prop) {
return orig_MGCopyAnswer(prop);
}
%ctor {
uint8_t MGCopyAnswer_arm64_impl[8] = {0x01, 0x00, 0x80, 0xd2, 0x01, 0x00, 0x00, 0x14};
const uint8_t* MGCopyAnswer_ptr = (const uint8_t*) MGCopyAnswer;
if (memcmp(MGCopyAnswer_ptr, MGCopyAnswer_arm64_impl, 8) == 0) {
MSHookFunction(MGCopyAnswer_ptr + 8, (void*)new_MGCopyAnswer_internal, (void**)&orig_MGCopyAnswer_internal);
} else {
MSHookFunction(MGCopyAnswer_ptr, (void*)new_MGCopyAnswer, (void**)&orig_MGCopyAnswer);
}
}
(This only checks for arm64 on 9.3.2. Other platforms may crash in different ways, and have different assembly code, so you may need to add additional conditions into enter the hook-MGCopyAnswer_internal branch. YMMV!)
Try this code:
#import <substrate.h>
static CFTypeRef (*orig_MGCopyAnswer)(CFStringRef str);
CFTypeRef new_MGCopyAnswer(CFStringRef str)
{
return orig_MGCopyAnswer(str);
}
%ctor
{
NSString *appID = [[NSBundle mainBundle] bundleIdentifier];
if ( appID && [appID isEqualToString:#"com.test.test"]) {
void * MGCopyAnswerFn = MSFindSymbol(NULL, "_MGCopyAnswer");
MSHookFunction(MGCopyAnswerFn, (void *) new_MGCopyAnswer, (void **)& orig_MGCopyAnswer);
}
}

The Future {blocking {created new Future{}}} - nested futures stops parents one

I've tried to model the situation I have in a real code.
The use case is simple:
There is:
Future {blocking {
// in there it calls nested futures
}}
More detailed (global Execution context is used as parent one, but there is was attemp to use separete one for children):
object ExContexts {
val main = scala.concurrent.ExecutionContext.Implicits.global
val ecChildren = scala.concurrent.ExecutionContext.fromExecutor(Executors.newFixedThreadPool(1))
}
object NestedFutures2 extends App {
import scala.concurrent.ExecutionContext.Implicits.global
val cores = Runtime.getRuntime.availableProcessors
val works = parentWork(ExContexts.main) // main EC
val result1: Seq[Seq[Future[String]]] = Await.result(Future.sequence(works), Duration.Inf)
println("parents are done their work")
val result2: Seq[String] = Await.result(Future.sequence(result1.flatten), Duration.Inf)
// ---
def parentWork(ex:ExecutionContext): Seq[Future[Seq[Future[String]]]] = {
val works: Seq[Future[Seq[Future[String]]]] =
(1 to cores * 2) map { x =>
Future {
blocking { // will create new thread/place if needed
val parentName = Thread.currentThread.getName
println("parent: " + parentName + " started an action")
val playFutureOutcomes: Seq[Future[String]] = (1 to 10) map {stuffId =>
childPlay(parentName = parentName)(ExContexts.ecChildren)
}
Thread.sleep(1000)
println(s"[${timeStamp()}] parent: " + parentName + " has finished the action")
playFutureOutcomes
}
}
}
works
}
def childPlay(parentName:String)(ex:ExecutionContext):Future[String] = {
Future {
Thread.sleep(2000) // two seconds play session
val threadName = Thread.currentThread.getName
// log
println("child: " + threadName + " of " + parentName + " parent")
Thread.currentThread.getName
}
}
def timeStamp(pattern:String = "ss:mm : hh"): String = {
val fmt = DateTimeFormat.forPattern(pattern)
fmt.print(DateTime.now)
}
}
From the output (5 of 8 parrent futures are done) I see that children make use of parents threads...:
[01:31 : 05] parent: ForkJoinPool-1-worker-5 has finished the action
[01:31 : 05] parent: ForkJoinPool-1-worker-11 has finished the action
[01:31 : 05] parent: ForkJoinPool-1-worker-1 has finished the action
[01:31 : 05] parent: ForkJoinPool-1-worker-3 has finished the action
[01:31 : 05] parent: ForkJoinPool-1-worker-7 has finished the action
child: ForkJoinPool-1-worker-13 of ForkJoinPool-1-worker-1 parent
child: ForkJoinPool-1-worker-5 of ForkJoinPool-1-worker-5 parent
child: ForkJoinPool-1-worker-1 of ForkJoinPool-1-worker-1 parent
child: ForkJoinPool-1-worker-11 of ForkJoinPool-1-worker-11 parent
child: ForkJoinPool-1-worker-3 of ForkJoinPool-1-worker-3 parent
child: ForkJoinPool-1-worker-7 of ForkJoinPool-1-worker-7 parent
child: ForkJoinPool-1-worker-13 of ForkJoinPool-1-worker-11 parent
...
I expect parents one to done their work in ~1 second as it was if we don't have childrent. Also I would expect to see two connecton pools instead of one.
Q: what would be the suggestion to achive it?
UPDATE:
I guess it is all about Join-Pool based upon Implicit.glocal is built. All nested Furue will be joined to one pool?
// What (I think) I see is that if we have 'global' execution context as parent/main,
// then whatever we pass as execution context to the child Future still will use global context
// and still will be using ONE connection pool.
// And then therefore wll have performance problem if children do not use 'blocking' -
// parents will be stuck in cores-long connection pool
// So: Children will 'inherit' execution context, but not 'blocking'
// and as children connected/joined to the execution context the parents will not be able to do
// anything about it but wait for the free space in the pool (when child is done)
// new additional threads will not be creating for the next parent because (i guess)
// Global execution context will not see the reason of/for it.
// Like a snapshot of the moment of time:
// Connection Pool: [ch1, ch2, ch3, p1]
// It things:Ok there is one parent (p1) in the pool if one more parent
// future will come I create for it new thread it the pool.
// But because we have more joined children than parents in the list
// the moment when Global ex context can help parent will never come.
Should then I not to use that global context if I want parents to be independant on childrent and vice versa? (funny how many people in Internet are playing with global only.)
Say I know ma app has 20 000 clients and each of them makes 1-100 sec long operations (op1->op1.op1) all the time. Then I just could dedicate one executon context with 20 000 connecton pool (max). And as many execution context as needed for all sort of long-running operations (parent->child where child is not reportng to the parent). Say: printingExCon, logExCon, readStufExCon, writeStuffExCon
But if I know that one oparation should include anoter one and they maybe joined then (only) I may use that global Ex context?
Otherwise if I would use global ex context as may man context - all and everyone would join to it and I would end up having performance problem that I explained at te beginning of this Sunday post..
UPDATE:
I wasted good chunk of time trying to understand why fixed version (with 'ex' passed to childPlay's Future{}(ex) was producing an output that ignore sleeps and behaves weired on many other cases. The problem was fixed when instead of running/buildng in IntellyJIDEA 14 (by CTRL-SHIFT+F10) i build it wit sbt run..

Linux kernel vfs_stat function does not return device id of the file

I am trying to get the device number of a file in kernel mode. The device id I am looking for is something which comes with stat:
Size: 1024 Blocks: 2 IO Block: 1024 directory
Device: 700h/1792d Inode: 2 Links: 3
Access: (0755/drwxr-xr-x) Uid: ( 0/ root) Gid: ( 0/ root)
Context: system_u:object_r:unlabeled_t:s0
I have written code using vfs_stat but do not get the same number
struct kstat sb;
int error = 0;
sb.rdev = 0;
error = vfs_fstat(fd, &sb);
if (error) {
monks_error("Could not get vfs stat %d", error);
}
if (sb.mode == 0060000) {
monks_info("The device number is %d", MINOR(sb.dev));
}
return sb.dev;
not sure what is wrong here?
Well, the code sample is insufficient to give a meaningful answer. Also you are inspecting sb.mode even if vfs_fstat failed and what's worse you are unconditionally returning sb.dev.
However, the obvious place to start digging is the stat syscall to see if it does anything to stuff obtained from vfs_fstat. It so happens it does as can be seen in cp_new_stat: tmp.st_dev = encode_dev(stat->dev);

Garbage Collection, pointers and scope in D

Apologies in advance about the long post - I'm having a problem I think might be related to garbage collection.
I have a class that wraps DMDScript like this:
/**
* Wrapper class for the DMDScript
*/
class ScriptingHost
{
protected static CallContext *cc ; // Call Context for interaction with the script.
protected static Program prg ; // Reference to program object (this is where the script buffer gets parsed)
static this()
{
// create our program instance
prg = new Program();
// create reference to call Context
cc = prg.callcontext;
Stdout( "cc.global: " )( cc.global ).newline ;
// add some built-in functions, like trace() and trigger()
DnativeFunction dnfTrace = new DnativeFunction( &jsTrace, "trace", 0, Dfunction.getPrototype() ) ;
DnativeFunction dnfTrigger = new DnativeFunction( &jsTrigger, "trigger", 0, Dfunction.getPrototype() ) ;
// add it to the call context
cc.global.Put("trace", dnfTrace , 0);
cc.global.Put("trigger", dnfTrigger , 0);
}
/***********************************************************************
* Helper functions for D<-->JS interaction
************************************************************************/
/**
* Trace (output)
*/
protected static void* jsTrace( Dobject pthis, CallContext* cc, Dobject othis, Value* ret, Value[] arglist)
{
Stdout( "<<" )( arglist ).newline ;
return null;
}
/**
* Trigger
*/
protected static void* jsTrigger( Dobject pthis, CallContext* cc, Dobject othis, Value* ret, Value[] arglist)
{
Stdout( "<<" )( arglist ).newline ;
return null;
}
}
So far, everything is fine and I can run the code with no errors.
Output:
cc.global: dmdscript_tango.dglobal.Dglobal
I also added a method to ScriptingHost that traced the cc.global object:
public static void testGlobal()
{
Stdout( "testGlobal: " )( cc.global ).newline.flush ;
}
...which also works fine - The problem arises when I try accessing it from outside the class ala:
int main()
{
Stdout( "DMDScriptTest" ).newline ;
ScriptingHost.testGlobal() ;
Stdout( "global: " )( ScriptingHost.global() ).newline.flush ;
ScriptingHost.testGlobal() ;
}
Then I get the following error:
cc.global: dmdscript_tango.dglobal.Dglobal
DMDScriptTest
testGlobal: dmdscript_tango.dglobal.Dglobal
object.Exception: Illegal Instruction
----------------
[ 5fd264] 0+0 ??? #0+1975211 :0
[ 404e05] 0+0 tango.text.convert.Layout.Layout!(char).Layout.parse.process #0+29 c:\dmd\dmd\bin\..\import\tango\text\convert\Layout.d:595
[ 404875] 0+0 tango.text.convert.Layout.Layout!(char).Layout.parse #0+65 c:\dmd\dmd\bin\..\import\tango\text\convert\Layout.d:603
[ 40463b] 0+0 tango.text.convert.Layout.Layout!(char).Layout.convert #0+34 c:\dmd\dmd\bin\..\import\tango\text\convert\Layout.d:347
[ 40418e] 0+0 tango.io.stream.Format.FormatOutput!(char).FormatOutput.print #0+67 c:\dmd\dmd\bin\..\import\tango\io\stream\Format.d:172
[ 40206c] 0+0 __Dmain #0+45 test2.d:87
[ 4380b5] 0+0 rt.compiler.dmd.rt.dmain2.main.runMain #0+119292 :0
[ 43800b] 0+0 rt.compiler.dmd.rt.dmain2.main.tryExec #0+119122 :0
[ 4380f3] 0+0 rt.compiler.dmd.rt.dmain2.main.runAll #0+119354 :0
[ 43800b] 0+0 rt.compiler.dmd.rt.dmain2.main.tryExec #0+119122 :0
[ 437fc3] 0+0 _main #0+119050 :0
[ 44c980] 0+0 _mainCRTStartup #0+203463 :0
[75e133c8] 0+0 ??? #0+1973388559 :0
[76f49ed0] 0+0 ??? #0+1991438359 :0
[76f49ea0] 0+0 ??? #0+1991438311 :0
global: unittest start
unittest end
Is anyone able to shed some light on the issue here - and perhaps how to work around it, please? :)
edit: I am using a windows D1-Tango setup. The version I'm using is the 0.99.9 Tango/DMD 1.056 Kai bundle .
thanks,
First of all, which operating system are you using? Based on the error I'm guessing windows? Which version of dmd/tango are you using? 32 bit or 64 bit? Try running your application through a disassembler and looking what instruction is listed at 5fd264 (search through the output). We should be able to help more with some of the information above.
What version of DMD are you using? If you're still using 1.067, are compiling in 64-bit mode and are using sufficiently ancient hardware, you may have a problem. 1.067 was the first version with 64-bit support and had a bug that would use the LAHF and SAHF instructions, which weren't supported on very old 64-bit CPUs.

Resources