From mboxrd@z Thu Jan 1 00:00:00 1970 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on polar.synack.me X-Spam-Level: X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,FREEMAIL_FROM autolearn=unavailable autolearn_force=no version=3.4.4 X-Received: by 10.129.87.209 with SMTP id l200mr9891521ywb.4.1470988617385; Fri, 12 Aug 2016 00:56:57 -0700 (PDT) X-Received: by 10.157.45.97 with SMTP id v88mr533763ota.4.1470988617344; Fri, 12 Aug 2016 00:56:57 -0700 (PDT) Path: eternal-september.org!reader01.eternal-september.org!reader02.eternal-september.org!news.eternal-september.org!news.eternal-september.org!feeder.eternal-september.org!usenet.blueworldhosting.com!feeder01.blueworldhosting.com!border2.nntp.dca1.giganews.com!nntp.giganews.com!c52no8348975qte.1!news-out.google.com!d68ni24919ith.0!nntp.google.com!f6no9334045ith.0!postnews.google.com!glegroupsg2000goo.googlegroups.com!not-for-mail Newsgroups: comp.lang.ada Date: Fri, 12 Aug 2016 00:56:57 -0700 (PDT) In-Reply-To: Complaints-To: groups-abuse@google.com Injection-Info: glegroupsg2000goo.googlegroups.com; posting-host=2a02:1205:c68c:9d90:b445:b1b2:fb8a:1ddd; posting-account=Pm0FhgoAAAAiPscNT3etSZ15tHNZGXm_ NNTP-Posting-Host: 2a02:1205:c68c:9d90:b445:b1b2:fb8a:1ddd References: User-Agent: G2/1.0 MIME-Version: 1.0 Message-ID: Subject: Re: How to kill GNAT DLL initialization? From: ahlan.marriott@gmail.com Injection-Date: Fri, 12 Aug 2016 07:56:57 +0000 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: quoted-printable Xref: news.eternal-september.org comp.lang.ada:31416 Date: 2016-08-12T00:56:57-07:00 List-Id: On Thursday, 11 August 2016 09:32:26 UTC+2, Dmitry A. Kazakov wrote: > On 10/08/2016 22:18, ahlan.marriott@gmail.com wrote: > > On Wednesday, 10 August 2016 14:52:33 UTC+2, Dmitry A. Kazakov wrote: > >> As it seems GNAT DLL may not have initialization code invoked in > >> DllMain. This inevitable deadlocks RTS. Removing user library-level > >> tasks does not help. The RTS itself contains library-level tasks. E.g. > >> when asynchronous select is used. > >> > >> Now the question is how to kill calls to initialization code from DllM= ain. > >> > >> for Library_Auto_Init use "false"; > >> > >> Is not enough. Are there other attributes I missed? > >> > >> (Maybe there is a way to remove DllMain from the external symbols list > >> during linking?) > >> > > We produce DLLs written using GNAT that are used by other languages - t= ypically C++ > > We don't explicitly run any initialisation code, the main procedure is = always empty. > > (although this is probably a left over from our ObjectAda days) > > If something has to be initialised then we put this into a > > procedure, export it and request that our C++ user calls this before c= alling any > > other routine. >=20 > Yes, that is my plan too. GNAT generates files b__dllname.ads/adb=20 > containing an initialization procedure dllnameinit. This must be called= =20 > to initialize the RTS. The problem is that it is called automatically=20 > upon DLL load on the context where it freezes. I must find a way to kill= =20 > that call. >=20 > > Here is a typical Gpr file for one of our Dlls. > > > > ------- > > project Monitor is > > > > package Naming is > > for Casing use "mixedcase"; > > end Naming; > > > > for Library_Name use "Monitor"; > > for Shared_Library_Prefix use ""; > > > > for Source_Dirs use ("W:\Source\Ada\Interfaces\Monitor", > > "W:\Source\Ada\Interfaces", > > "W:\Source\Ada\Shared", > > "W:\Source\Ada\Open\Shared", > > "W:\Source\Ada\Open\Shared\Windows"); > > > > for Library_Interface use ("Monitor_Interface"); > > > > for Object_Dir use "objects"; > > > > for Library_Options use ("-LW:\Product\Windows", "resources.o"); > > for Library_Dir use "W:\Product\Windows"; > > for Library_Ali_Dir use "D:\Binary\Ada\Interfaces\Monitor"; > > for Library_Kind use "dynamic"; > > for Library_Standalone use "encapsulated"; > > > > package Pretty_Printer is > > for Default_Switches ("ada") use ("-i2", "-M120", "-aL", "-A1", "= -A4"); > > end Pretty_Printer; > > > > package Builder is > > for Default_Switches ("ada") use ("-s", "-g"); > > end Builder; > > > > package Compiler is > > for Default_Switches ("ada") use > > ("-O1", "-gnatQ", "-gnata", "-gnato", "-g", "-gnat12", > > "-gnatwcehijkmopruvz.c.n.p.t.w.x", "-gnatykmpM120"); > > end Compiler; > > > > package Binder is > > for Default_Switches ("ada") use ("-E"); > > end Binder; > > > > end Monitor; >=20 > My gpr project is no different, except that Library_Interface is a=20 > package with some procedures. >=20 > > ------- > > > > and the main package. > > > > ------- > > with Monitor_Interface; --> UD: Drag in Code > > > > procedure Monitor is > > begin > > null; > > end Monitor; > > ------- > > > > Monitor_Interface ads exports all the procedures that the DLL > > provides and the Adb implements them. >=20 > I found that my version of GNAT puts the DLL initialization program into= =20 > the .ctor section. That causes it called regardless anything. >=20 > --=20 > Regards, > Dmitry A. Kazakov > http://www.dmitry-kazakov.de Dear Dmitry, I can't help but feel that you are going about this the wrong way. I don't think you should be trying to prevent initialisation. If you succeed then your DLL probably won't work because things need to be = initialised. We do all our PC programming in Ada. Unfortunately not everyone is so enlightened and so we have to produce DLLs= for other departments to use. Consequently we have over the years produced a good many Windows DLLs that = are used by a variety of languages, including Microsoft C++ and even Ada. (We do in fact have a problem when our DLLs are called by an Ada program th= at uses Gtk later than 3.8.2 running on Windows XP - however I suspect that= this isn't the problem you are experiencing) Although our main is empty this is just because our main package has no cod= e - the other packages have normal initialisation code and of course are el= aborated. The three things we need to be careful with are: 1) The interface has to use the C calling convention - including callbacks. 2) We don't attempt to propagate exceptions. Our interfaces are all functio= ns that return a return code. Exceptions in the DLL are caught in the inter= face procedures and converted into an error code that is passed back to the= caller. 3) Tasks must not be created either in package bodies nor in their elaborat= ion. My guess is this is where your problem really lies. You can't have sta= tic tasks, only dynamic tasks and these must not be created in the package = body - i.e. as part of the package elaboration or between the package begin= and end. The task restriction is normally where we trip over. So I suggest that you = check very carefully where your tasks are being created. They can only be c= reated as a result of being called by the DLL user not automatically by the= DLL.=20 This is why most of our DLLs provide a function called Initialise that we r= equire the DLL user to call before using any other of the provided function= s. We also usually have a Finalise procedure that the DLL user must call so= that we can terminate all our tasks - otherwise the main program won't exi= t. Really, creating DLLs using a recent version (>=3DGPL;2014) of GNAT isn't a= problem. It is a bit more complicated if you are using a older version of GNAT becau= se GNAT did not automatically make the transitive closure and on really old= versions of GNAT you had to manually cause the DLL packages to be elaborat= ed using AdaInit - but that is another story... Hoping this helps, MfG Ahlan