Crash in Dylib

Mac OSX specific forum
simberr
User
User
Posts: 46
Joined: Sun Jun 10, 2018 12:54 pm

Crash in Dylib

Post by simberr »

I hope that someone can point me in the right direction with a crash that I am receiving on a call to a Dylib.

I have a dylib that I created in PB. It is a simple dylib with a single exported function. The definition is:

Code: Select all

ProcedureCDLL doTTTest()
I place the dylib in the main program's Resources folder. I call the dylib procedure with the following code in my main program.

Code: Select all

PrototypeC pCall()

Procedure btnDoneClick(ev.i)

  f.s = sbString::folderResources() + "TTest.dylib"

  If OpenLibrary(0, f)
    callTTest.pCall = GetFunction(0, "doTTTest")
    callTTest()       <---- CRASH HERE
    CloseLibrary(0)
  EndIf
  
EndProcedure
The first time that I call the procedure it works fine. The second time it is called then I get the crash. The Apple report is below:

Code: Select all

Process:               containercontrol [3860]
Path:                  /Users/USER/Downloads/*/containercontrol.app/Contents/MacOS/containercontrol
Identifier:            com.simcarsoftware.containercontrol
Version:               0.1 (0.1)
Code Type:             X86-64 (Native)
Parent Process:        ??? [1]
Responsible:           containercontrol [3860]
User ID:               501

Date/Time:             2018-09-01 12:22:34.600 +0100
OS Version:            Mac OS X 10.12.6 (16G1510)
Report Version:        12
Anonymous UUID:        555690B2-41E7-73B2-7E87-EA9AEAB6D6B1


Time Awake Since Boot: 2300000 seconds

System Integrity Protection: enabled

Crashed Thread:        0  Dispatch queue: com.apple.main-thread

Exception Type:        EXC_CRASH (SIGABRT)
Exception Codes:       0x0000000000000000, 0x0000000000000000
Exception Note:        EXC_CORPSE_NOTIFY

Termination Reason:    Namespace OBJC, Code 0x1

Thread 0 Crashed:: Dispatch queue: com.apple.main-thread
0   libsystem_kernel.dylib        	0x00007fffcf6d40aa __abort_with_payload + 10
1   libsystem_kernel.dylib        	0x00007fffcf6d0326 abort_with_payload_wrapper_internal + 90
2   libsystem_kernel.dylib        	0x00007fffcf6d02cc abort_with_reason + 22
3   libobjc.A.dylib               	0x00007fffcecc6e1b _objc_fatalv(unsigned long long, unsigned long long, char const*, __va_list_tag*) + 102
4   libobjc.A.dylib               	0x00007fffcecc6cc6 _objc_fatal(char const*, ...) + 146
5   libobjc.A.dylib               	0x00007fffcecd1e78 (anonymous namespace)::AutoreleasePoolPage::busted(bool) + 144
6   libobjc.A.dylib               	0x00007fffcecba078 (anonymous namespace)::AutoreleasePoolPage::pop(void*) + 80
7   com.apple.CoreFoundation      	0x00007fffb9994b86 _CFAutoreleasePoolPop + 22
8   com.apple.Foundation          	0x00007fffbb404e90 -[NSAutoreleasePool release] + 146
9   TTest.dylib                   	0x0000000109bd4a3d 0x109bd1000 + 14909
10  TTest.dylib                   	0x0000000109bd5e79 0x109bd1000 + 20089
11  TTest.dylib                   	0x0000000109bd60de 0x109bd1000 + 20702
12  TTest.dylib                   	0x0000000109bd25d5 0x109bd1000 + 5589
The above is the short version of the crash report as the report is stating that the crash occurred in Thread 0, so that is what is included.

I am at a loss to understand what has happened and why. I have tried compiling the dylib with thread safe on and off. I have tried with ProcedureDLL and Prototype and then with ProcedureCDLL and PrototypeC. Whatever I try I get exactly the same result.

It has to be something I have done - what?

Simon.
simberr
User
User
Posts: 46
Joined: Sun Jun 10, 2018 12:54 pm

Re: Crash in Dylib

Post by simberr »

I have now narrowed down the crash to a specific situation.

If I send and/or receive an integer value then no crash.
If I send and/or receive a double value then no crash.
If I send and/or receive a string value then no crash.

It is when I am asking the dylib routine to open a window within the dylib. In this situation the window opens and reacts correctly in the first instance. If I go to open the window a second time then the app crashes.

It has to be something to do with the internal window handling within a dylib.

Can anybody help?

Simon.
wilbert
PureBasic Expert
PureBasic Expert
Posts: 3870
Joined: Sun Aug 08, 2004 5:21 am
Location: Netherlands

Re: Crash in Dylib

Post by wilbert »

I think it might have to do with autorelease pools.

A few years ago Fred wrote in another topic
PB GUI functions are not meant to be called from a dylib
viewtopic.php?p=490879#p490879

Does that help ?
Windows (x64)
Raspberry Pi OS (Arm64)
simberr
User
User
Posts: 46
Joined: Sun Jun 10, 2018 12:54 pm

Re: Crash in Dylib

Post by simberr »

Wilbert

Yes, it does seem to be something to do with the autorelease pool.

Fred suggested in his post that

Code: Select all

event = WindowEvent()
could be used to clear/reset the pool.

I have now tried this in various places but I still get the crash.

If the GUI elements are not supposed to be called/used within a dylib then that is a real shame. I had wanted to use the dynamic ability to call dylibs from my main app which gave me some huge advantages in my main app. I have successfully employed this principle in the main parts of my app and have just come to implementing the GUI elements and hit this issue. If I cannot find a workaround then I will have to completely review a major part of my implementation and that is a LOT of work.

Having said that, as this is a similar limitation in my main app development environment I cannot get too upset with PB! That's life, I guess...
wilbert
PureBasic Expert
PureBasic Expert
Posts: 3870
Joined: Sun Aug 08, 2004 5:21 am
Location: Netherlands

Re: Crash in Dylib

Post by wilbert »

Does it help you create a pool yourself ?

Code: Select all

ProcedureCDLL Test()
  Protected Pool = CocoaMessage(0, 0, "NSAutoreleasePool new")
  
  ; Here goes the procedure code including OpenWindow()
  
  CocoaMessage(0, Pool, "release")
EndProcedure
Windows (x64)
Raspberry Pi OS (Arm64)
simberr
User
User
Posts: 46
Joined: Sun Jun 10, 2018 12:54 pm

Re: Crash in Dylib

Post by simberr »

Wilbert

You are amazing!

It seems that this works. In a simple test I could call the dylib procedure on a number of occasions and they all opened and closed correctly, returning the correct values from the sent values, too.

Obviously I have to extensively test this but it seems that you have solved my issue.

Thank you so much.

Simon.
simberr
User
User
Posts: 46
Joined: Sun Jun 10, 2018 12:54 pm

Re: Crash in Dylib

Post by simberr »

I spoke too soon!

After working in a simple test I am now finding that it does not work any more. I am still running my test in the exact same place with no changes but I am still getting the crash after the first iteration.

It now makes no sense to me that implementing the code worked a hundred times with no problem and then it started crashing after a single iteration again.

Am I jinxed?

S.
wilbert
PureBasic Expert
PureBasic Expert
Posts: 3870
Joined: Sun Aug 08, 2004 5:21 am
Location: Netherlands

Re: Crash in Dylib

Post by wilbert »

Did you start calling additional procedures from your dylib ?
If so, try if adding an autorelease pool to every ProcedureCDLL procedure makes a difference.
Windows (x64)
Raspberry Pi OS (Arm64)
simberr
User
User
Posts: 46
Joined: Sun Jun 10, 2018 12:54 pm

Re: Crash in Dylib

Post by simberr »

If I understand you correctly I should add the before and after code you specified to every procedure that I have within my dylib?

Ok, I will try that.

I will come back with the results.

Simon.
wilbert
PureBasic Expert
PureBasic Expert
Posts: 3870
Joined: Sun Aug 08, 2004 5:21 am
Location: Netherlands

Re: Crash in Dylib

Post by wilbert »

simberr wrote:If I understand you correctly I should add the before and after code you specified to every procedure that I have within my dylib?
Only the procedures that are to be called from outside the dylib.
For private procedures inside your dylib it shouldn't be required.
Windows (x64)
Raspberry Pi OS (Arm64)
simberr
User
User
Posts: 46
Joined: Sun Jun 10, 2018 12:54 pm

Re: Crash in Dylib

Post by simberr »

I coded my dylib for the external procedures (those with ProcedureCDLL) to open and close an AutoTReleasePool. This solution now works for about 3 iterations before crashing.

The Mac report is:

Code: Select all

Application Specific Information:
objc[34707]: Invalid or prematurely-freed autorelease pool 0x7fdaaa10c9f0. Set a breakpoint on objc_autoreleasePoolInvalid to debug. Proceeding anyway because the app is old (SDK version 10.9.0). Memory errors are likely.
I don't use Xcode and don't really understand the error report. I can see (obviously) that it is a memory problem but beyond that ...

I am coming to the conclusion that I just should not use a GUI based dylib. Normal dylib functions (send/return integers, doubles and strings) I can get to work correctly and consistently. I am just attempting to create a completely dynamic app that I can drive by database table entries. By that I mean defining flow and functions completely driven by setting up a database of what a user transaction should look like and then supplying base dylibs that work in a single scenario. The ultimate user can then completely modify the standard system by creating their own dylibs (in PB) and telling the database what to use instead or as well as the base.

This will allow windows and functions to be added/deleted/reordered at will with no recompilation of any of the main system programs, just simple changes to the database flow.

I have everything working with the exception of calling a dylib for the GUI windows. I have been thinking of an option of creating apps for the GUI elements rather than dylibs. I am thinking this might be the better option as that works fine (I can easily call a dynamic GUI window from within the main system). The only issue then is letting the main system know that the called GUI window has finished and that the main system needs to interrogate the database again to determine any changes made. I am beginning to think that this is where I should be concentrating rather than playing about with GUI dylibs.

Wilbert, as I know you are a real expert in PB and MacOS, I would really appreciate your advice in this.

Simon.
wilbert
PureBasic Expert
PureBasic Expert
Posts: 3870
Joined: Sun Aug 08, 2004 5:21 am
Location: Netherlands

Re: Crash in Dylib

Post by wilbert »

simberr wrote:I don't use Xcode and don't really understand the error report. I can see (obviously) that it is a memory problem but beyond that ...
Unfortunately I also don't know how to solve this error :?
simberr wrote:I am coming to the conclusion that I just should not use a GUI based dylib.
That might be best.
Maybe you can let the dylib return information to the main application on how to create the gui.
That way you could still have the information on how to build the gui inside the dylib but do the actual gui creation in the main application.
Windows (x64)
Raspberry Pi OS (Arm64)
simberr
User
User
Posts: 46
Joined: Sun Jun 10, 2018 12:54 pm

Re: Crash in Dylib

Post by simberr »

Thank you.

I think I will go down the route of not using dylibs for any GUI part of the app. Dynamically creating the GUI from within the main app with data supplied by the dylib would seem the better option.

Thank you for your time and effort. It is really appreciated from this newcomer to PB.

Simon.
User avatar
mk-soft
Always Here
Always Here
Posts: 5406
Joined: Fri May 12, 2006 6:51 pm
Location: Germany

Re: Crash in Dylib

Post by mk-soft »

The Purebasic objects in the dylib are not the same as in the main program.

Code: Select all

ImportC ""
  PB_Window_Objects.i
  PB_Gadget_Objects.i
  PB_Image_Objects.i
;  PB_Font_Objects.i
EndImport
ProcedureCDLL OpenMain(x = 10, y = 10, width = 550, height = 420)
  MessageRequester("DyLib" , Hex(PB_Gadget_Objects))
EndProcedure
[/size]
I have given up a small test program.

So the windows, gadgets, menus, etc are not created in the right environment.

Maybe it works if you pass the functions to create objects for windows, gadgets, menus, etc to dylib.

You must also make sure that the objects are not created from a thread. To create the objects from a thread you have to use a detour via "Postevent".

You could pass the following functions from the main program to dylib
- CreateWindow(...)
- CreateGadget(Type, Gadget, ...)
- CreateMenu(...)
- etc.

Maybe you can adapt a few codes from me for it
Link: viewtopic.php?f=12&t=70119

Part

Code: Select all

Procedure CreateGadget(GadgetType, Name.s, Gadget, x, y, dx, dy, Text.s, Param1, Param2, Param3, Flags)
    Protected result, const.s, rt.s
    
    Select GadgetType
      Case #PB_GadgetType_Button : result = ButtonGadget(Gadget, x, y, dx, dy, Text, Flags)
      Case #PB_GadgetType_ButtonImage : result = ButtonImageGadget(Gadget, x, y, dx, dy, Param1, Flags)
      Case #PB_GadgetType_Calendar : result = CalendarGadget(Gadget, x, y, dx, dy, Param1, Flags)
      Case #PB_GadgetType_Canvas : result = CanvasGadget(Gadget, x, y, dx, dy, Flags)
[/size]

P.S.
What I haven't tested yet is whether "PostEvent" from a dylib works.
Link: viewtopic.php?f=12&t=66180
My Projects ThreadToGUI / OOP-BaseClass / EventDesigner V3
PB v3.30 / v5.75 - OS Mac Mini OSX 10.xx - VM Window Pro / Linux Ubuntu
Downloads on my Webspace / OneDrive
Post Reply