Reproducible code: DLL calling Firebird crashes

classic Classic list List threaded Threaded
26 messages Options
12
Reply | Threaded
Open this post in threaded view
|

Reproducible code: DLL calling Firebird crashes

Reinier Olislagers
Apparently my crashes in a dll that use Firebird have to do with
initialization sections in my business layer creating a single instance
of my db layer.

Distilled reproducible code that demonstrates problem:
https://bitbucket.org/reiniero/fpc_laz_patch_playground/downloads/dllcrash.zip

1. Please update your Firebird server details in dbinterface.pas to your
situation (hostname etc)
2. In businesslayer.pas, $define CRASH to see the problem.
The code in question is:
initialization
  DBLayer:=TDBInterface.Create;

finalization
  DBLayer.Free;
... so probably initialization order plays a part?!?

How should I fix this?

Thanks,
Reinier
_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: Reproducible code: DLL calling Firebird crashes

Mark Morgan Lloyd-5
Reinier Olislagers wrote:

> Apparently my crashes in a dll that use Firebird have to do with
> initialization sections in my business layer creating a single instance
> of my db layer.
>
> Distilled reproducible code that demonstrates problem:
> https://bitbucket.org/reiniero/fpc_laz_patch_playground/downloads/dllcrash.zip
>
> 1. Please update your Firebird server details in dbinterface.pas to your
> situation (hostname etc)
> 2. In businesslayer.pas, $define CRASH to see the problem.
> The code in question is:
> initialization
>   DBLayer:=TDBInterface.Create;
>
> finalization
>   DBLayer.Free;
> ... so probably initialization order plays a part?!?
>
> How should I fix this?

What happens if you move the responsibility for initialising and closing
the database connection to the app-level code? In other words, the app
does something like

   writeln('Starting demo');
   writeln('TheAnswer is:');
   InitialiseBackend;
   try
     writeln(TheAnswer)
   finally
     FinaliseBackend
   end;
   writeln('Ending demo');

--
Mark Morgan Lloyd
markMLl .AT. telemetry.co .DOT. uk

[Opinions above are the author's, not those of his employers or colleagues]
_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: Reproducible code: DLL calling Firebird crashes

Reinier Olislagers
On 29/09/2014 11:19, Mark Morgan Lloyd wrote:

> Reinier Olislagers wrote:
>> 2. In businesslayer.pas, $define CRASH to see the problem.
>> The code in question is:
>> initialization
>>   DBLayer:=TDBInterface.Create;
>>
>> finalization
>>   DBLayer.Free;
>> ... so probably initialization order plays a part?!?
>>
>> How should I fix this?
>
> What happens if you move the responsibility for initialising and closing
> the database connection to the app-level code? In other words, the app
> does something like
As the demo indicates, that does work (undefine CRASH).

What I would like to know what is the cause of this problem - dlls being
loaded before some kind - what kind? - of initialization is complete?

Anyway, I'll keep digging; probably first looking at geting postgresql
support in anyway.
_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: Reproducible code: DLL calling Firebird crashes

Reinier Olislagers
In reply to this post by Mark Morgan Lloyd-5
On 29/09/2014 11:19, Mark Morgan Lloyd wrote:
> Reinier Olislagers wrote:
> What happens if you move the responsibility for initialising and closing
> the database connection to the app-level code? In other words, the app
> does something like

Ok, after eliminating some PEBKAC, my real dll works flawlessly.

Still would like to know the background to this but glad it works.

Thanks a lot, Mark!

Regards,
Reinier

_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: Reproducible code: DLL calling Firebird crashes

José Mejuto
In reply to this post by Reinier Olislagers
El 29/09/2014 a las #4, Reinier Olislagers escribió:

> What I would like to know what is the cause of this problem - dlls being
> loaded before some kind - what kind? - of initialization is complete?
>
> Anyway, I'll keep digging; probably first looking at geting postgresql
> support in anyway.
> _______________________________________________

Hello,

You must not initialize dbengine in the Initialization section and must
not finalize it in that place (maybe only as last chance) because
initialization order and finalization order is undefined by fpc and
finalization of your code could happen after the whole DB structure has
been finished, so the call to "DBLayer.Free" could try to free an object
controlled by an engine which is not loaded yet.


--

_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: Reproducible code: DLL calling Firebird crashes

Reinier Olislagers
On 29/09/2014 16:51, José Mejuto wrote:
> El 29/09/2014 a las #4, Reinier Olislagers escribió:
> You must not initialize dbengine in the Initialization section and must
> not finalize it in that place (maybe only as last chance) because
> initialization order and finalization order is undefined by fpc and
> finalization of your code could happen after the whole DB structure has
> been finished, so the call to "DBLayer.Free" could try to free an object
> controlled by an engine which is not loaded yet.

Hi José,

Thanks, I'll just add a note to the shared library page of the wiki.
_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: Reproducible code: DLL calling Firebird crashes

Mark Morgan Lloyd-5
In reply to this post by Reinier Olislagers
Reinier Olislagers wrote:

> On 29/09/2014 11:19, Mark Morgan Lloyd wrote:
>> Reinier Olislagers wrote:
>>> 2. In businesslayer.pas, $define CRASH to see the problem.
>>> The code in question is:
>>> initialization
>>>   DBLayer:=TDBInterface.Create;
>>>
>>> finalization
>>>   DBLayer.Free;
>>> ... so probably initialization order plays a part?!?
>>>
>>> How should I fix this?
>> What happens if you move the responsibility for initialising and closing
>> the database connection to the app-level code? In other words, the app
>> does something like
> As the demo indicates, that does work (undefine CRASH).
>
> What I would like to know what is the cause of this problem - dlls being
> loaded before some kind - what kind? - of initialization is complete?
>
> Anyway, I'll keep digging; probably first looking at geting postgresql
> support in anyway.

No, your example shows an implicit initialisation when the backend is
accessed. I was suggesting an explicit initialisation, so that the app
can if necessary tell the backend what localisation conventions to use.
OK, it's an excuse but it gets you out of the current hole.

In the longer term I think this probably merits a bug report, so that
library initialisation etc. can be explored. This does look like a
sequencing issue rather than something being on the wrong heap.

--
Mark Morgan Lloyd
markMLl .AT. telemetry.co .DOT. uk

[Opinions above are the author's, not those of his employers or colleagues]
_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: Reproducible code: DLL calling Firebird crashes

Reinier Olislagers
On 29/09/2014 17:41, Mark Morgan Lloyd wrote:

> Reinier Olislagers wrote:
>> On 29/09/2014 11:19, Mark Morgan Lloyd wrote:
>>> Reinier Olislagers wrote:
>>>> 2. In businesslayer.pas, $define CRASH to see the problem.
>>>> The code in question is:
>>>> initialization
>>>>   DBLayer:=TDBInterface.Create;
>>>>
>>>> finalization
>>>>   DBLayer.Free;
>>>> ... so probably initialization order plays a part?!?
>>>>
>>>> How should I fix this?
>>> What happens if you move the responsibility for initialising and closing
>>> the database connection to the app-level code? In other words, the app
>>> does something like
>> As the demo indicates, that does work (undefine CRASH).
>>
>> What I would like to know what is the cause of this problem - dlls being
>> loaded before some kind - what kind? - of initialization is complete?
>>
>> Anyway, I'll keep digging; probably first looking at geting postgresql
>> support in anyway.
>
> No, your example shows an implicit initialisation when the backend is
> accessed.
Agreed... but as that code works there's no reason to suspect your
approach won't work & my finished program sucesfully uses your approach ;)

Re bug report: agreed. I'll raise it.

_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: Reproducible code: DLL calling Firebird crashes

Mark Morgan Lloyd-5
Reinier Olislagers wrote:

> On 29/09/2014 17:41, Mark Morgan Lloyd wrote:
>> Reinier Olislagers wrote:
>>> On 29/09/2014 11:19, Mark Morgan Lloyd wrote:
>>>> Reinier Olislagers wrote:
>>>>> 2. In businesslayer.pas, $define CRASH to see the problem.
>>>>> The code in question is:
>>>>> initialization
>>>>>   DBLayer:=TDBInterface.Create;
>>>>>
>>>>> finalization
>>>>>   DBLayer.Free;
>>>>> ... so probably initialization order plays a part?!?
>>>>>
>>>>> How should I fix this?
>>>> What happens if you move the responsibility for initialising and closing
>>>> the database connection to the app-level code? In other words, the app
>>>> does something like
>>> As the demo indicates, that does work (undefine CRASH).
>>>
>>> What I would like to know what is the cause of this problem - dlls being
>>> loaded before some kind - what kind? - of initialization is complete?
>>>
>>> Anyway, I'll keep digging; probably first looking at geting postgresql
>>> support in anyway.
>> No, your example shows an implicit initialisation when the backend is
>> accessed.
> Agreed... but as that code works there's no reason to suspect your
> approach won't work & my finished program sucesfully uses your approach ;)
>
> Re bug report: agreed. I'll raise it.

Jose's comment about not (in effect) putting TIBConnection.Create() in
the initialisation block of a program (hence of a DLL or .so) is
interesting. Assuming that he is correct I think it's worth wondering
/why/ he's correct, and if that is in fact a symptom of something wrong
with the FPC initialisation sequence.

If he's correct, I'd expect the problem to persist even if your
businesslayer DLL were loaded on-demand rather than at the whim of the
OS: the binary state of the DLL/so in memory would be inappropriate for
reliable operation.

If you still have problems when you call TIBConnection.Create() after
all initialisation is complete, then you need to consider whether any
state in the DLL/so has to be transferred to the main program. Hopefully
you don't need to get involved with that.

A final thing to consider is that if there is an asynchronous element in
database initialisation it could end up being difficult for the main
program to check that the DLL/so was ready to use.

--
Mark Morgan Lloyd
markMLl .AT. telemetry.co .DOT. uk

[Opinions above are the author's, not those of his employers or colleagues]
_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: Reproducible code: DLL calling Firebird crashes

Reinier Olislagers
In reply to this post by Reinier Olislagers
On 29/09/2014 19:30, Reinier Olislagers wrote:
> Re bug report: agreed. I'll raise it.

http://bugs.freepascal.org/view.php?id=26801

_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: Reproducible code: DLL calling Firebird crashes

Mark Morgan Lloyd-5
Reinier Olislagers wrote:
> On 29/09/2014 19:30, Reinier Olislagers wrote:
>> Re bug report: agreed. I'll raise it.

Jonas has already closed it, noting

"http://msdn.microsoft.com/en-us/library/windows/desktop/ms682583%28v=vs.85%29.aspx

"***
The entry-point function should perform only simple initialization or
termination tasks. It must not call the LoadLibrary or LoadLibraryEx
function (or a function that calls these functions), because this may
create dependency loops in the DLL load order. This can result in a DLL
being used before the system has executed its initialization code.
***

"I.e., what you are doing is unsupported ("must not call the LoadLibrary
or LoadLibraryEx function"). I think that on most unix platforms, trying
to load libraries from other the init function of other libraries is not
supported either."

However I'd precede that by a thought based on what Jose said. In your
example, you're opening the database in the initialisation block of
businesslayer.pas, which is invoked at an arbitrary position in the init
sequence of the DLL/so. If that operation were moved instead to the
initialisation block of testdbdll.lpr, which in the context of the
DLL/so is analogous to a program's main block, it might work.

If having the open operation in testdbdll.lpr works but having it in
businesslayer.pas doesn't, then it's fair to ask why in the context of
FPC (hence my suggestion of a bug report). If neither works, then it's
presumably explained by Jonas's note i.e. it's a "feature" in the
context of the library loader.

In practice, I still think it's best for the main program to tell the
database when and how to initialise, since there's things that it might
know about the user's intentions or environment that aren't known by the
dynamically-loaded libraries (crude example: you might want to know the
compile-time name of the project of which the main program was a part).

--
Mark Morgan Lloyd
markMLl .AT. telemetry.co .DOT. uk

[Opinions above are the author's, not those of his employers or colleagues]
_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: Reproducible code: DLL calling Firebird crashes

Michael Van Canneyt


On Tue, 30 Sep 2014, Mark Morgan Lloyd wrote:

> Reinier Olislagers wrote:
>> On 29/09/2014 19:30, Reinier Olislagers wrote:
>>> Re bug report: agreed. I'll raise it.
>
> Jonas has already closed it, noting
>
> "http://msdn.microsoft.com/en-us/library/windows/desktop/ms682583%28v=vs.85%29.aspx
>
> "***
> The entry-point function should perform only simple initialization or
> termination tasks. It must not call the LoadLibrary or LoadLibraryEx function
> (or a function that calls these functions), because this may create
> dependency loops in the DLL load order. This can result in a DLL being used
> before the system has executed its initialization code.
> ***
>
> "I.e., what you are doing is unsupported ("must not call the LoadLibrary or
> LoadLibraryEx function"). I think that on most unix platforms, trying to load
> libraries from other the init function of other libraries is not supported
> either."
>
> However I'd precede that by a thought based on what Jose said. In your
> example, you're opening the database in the initialisation block of
> businesslayer.pas, which is invoked at an arbitrary position in the init
> sequence of the DLL/so. If that operation were moved instead to the
> initialisation block of testdbdll.lpr, which in the context of the DLL/so is
> analogous to a program's main block, it might work.

No. this is not correct. For a library, this is analogous to initialization code of a unit, it's just the 'last' unit being initialized.

Michael.
_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: Reproducible code: DLL calling Firebird crashes

Mark Morgan Lloyd-5
Michael Van Canneyt wrote:

> On Tue, 30 Sep 2014, Mark Morgan Lloyd wrote:
>
>> Reinier Olislagers wrote:
>>> On 29/09/2014 19:30, Reinier Olislagers wrote:
>>>> Re bug report: agreed. I'll raise it.
>>
>> Jonas has already closed it, noting
>>
>> "http://msdn.microsoft.com/en-us/library/windows/desktop/ms682583%28v=vs.85%29.aspx 
>>
>>
>> "***
>> The entry-point function should perform only simple initialization or
>> termination tasks. It must not call the LoadLibrary or LoadLibraryEx
>> function (or a function that calls these functions), because this may
>> create dependency loops in the DLL load order. This can result in a
>> DLL being used before the system has executed its initialization code.
>> ***
>>
>> "I.e., what you are doing is unsupported ("must not call the
>> LoadLibrary or LoadLibraryEx function"). I think that on most unix
>> platforms, trying to load libraries from other the init function of
>> other libraries is not supported either."
>>
>> However I'd precede that by a thought based on what Jose said. In your
>> example, you're opening the database in the initialisation block of
>> businesslayer.pas, which is invoked at an arbitrary position in the
>> init sequence of the DLL/so. If that operation were moved instead to
>> the initialisation block of testdbdll.lpr, which in the context of the
>> DLL/so is analogous to a program's main block, it might work.
>
> No. this is not correct. For a library, this is analogous to
> initialization code of a unit, it's just the 'last' unit being initialized.

Does the main program explicitly call the initialisation entry point of
the (dynamically-loaded) library, or it this done by the OS? I was under
the impression that the two were basically asynchronous and (as a
particular example) both the program and the library would have distinct
copies of the system unit with their own global variables etc. hence the
memory manager problem.

--
Mark Morgan Lloyd
markMLl .AT. telemetry.co .DOT. uk

[Opinions above are the author's, not those of his employers or colleagues]
_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: Reproducible code: DLL calling Firebird crashes

Michael Van Canneyt


On Tue, 30 Sep 2014, Mark Morgan Lloyd wrote:

> Michael Van Canneyt wrote:
>> On Tue, 30 Sep 2014, Mark Morgan Lloyd wrote:
>>
>>> Reinier Olislagers wrote:
>>>> On 29/09/2014 19:30, Reinier Olislagers wrote:
>>>>> Re bug report: agreed. I'll raise it.
>>>
>>> Jonas has already closed it, noting
>>>
>>> "http://msdn.microsoft.com/en-us/library/windows/desktop/ms682583%28v=vs.85%29.aspx 
>>>
>>> "***
>>> The entry-point function should perform only simple initialization or
>>> termination tasks. It must not call the LoadLibrary or LoadLibraryEx
>>> function (or a function that calls these functions), because this may
>>> create dependency loops in the DLL load order. This can result in a DLL
>>> being used before the system has executed its initialization code.
>>> ***
>>>
>>> "I.e., what you are doing is unsupported ("must not call the LoadLibrary
>>> or LoadLibraryEx function"). I think that on most unix platforms, trying
>>> to load libraries from other the init function of other libraries is not
>>> supported either."
>>>
>>> However I'd precede that by a thought based on what Jose said. In your
>>> example, you're opening the database in the initialisation block of
>>> businesslayer.pas, which is invoked at an arbitrary position in the init
>>> sequence of the DLL/so. If that operation were moved instead to the
>>> initialisation block of testdbdll.lpr, which in the context of the DLL/so
>>> is analogous to a program's main block, it might work.
>>
>> No. this is not correct. For a library, this is analogous to initialization
>> code of a unit, it's just the 'last' unit being initialized.
>
> Does the main program explicitly call the initialisation entry point of the
> (dynamically-loaded) library, or it this done by the OS? I was under the
> impression that the two were basically asynchronous and (as a particular
> example) both the program and the library would have distinct copies of the
> system unit with their own global variables etc. hence the memory manager
> problem.

The memory manager problem is completely unrelated to this.
DLL and calling program simply have different copies of the FPC memory manager.
That is what needs to be solved with dynamic packages.

As far as I know, the initialization entry point is called automatically.
But the compiler experts should confirm this. IIRC the behaviour changed
as the support for libraries improved;

Michael.

_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: Reproducible code: DLL calling Firebird crashes

Mark Morgan Lloyd-5
Michael Van Canneyt wrote:

>>>> However I'd precede that by a thought based on what Jose said. In
>>>> your example, you're opening the database in the initialisation
>>>> block of businesslayer.pas, which is invoked at an arbitrary
>>>> position in the init sequence of the DLL/so. If that operation were
>>>> moved instead to the initialisation block of testdbdll.lpr, which in
>>>> the context of the DLL/so is analogous to a program's main block, it
>>>> might work.
>>>
>>> No. this is not correct. For a library, this is analogous to
>>> initialization code of a unit, it's just the 'last' unit being
>>> initialized.
>>
>> Does the main program explicitly call the initialisation entry point
>> of the (dynamically-loaded) library, or it this done by the OS? I was
>> under the impression that the two were basically asynchronous and (as
>> a particular example) both the program and the library would have
>> distinct copies of the system unit with their own global variables
>> etc. hence the memory manager problem.
>
> The memory manager problem is completely unrelated to this. DLL and
> calling program simply have different copies of the FPC memory manager.
> That is what needs to be solved with dynamic packages.

Yes, agreed. Except that if cmem (or whatever) isn't being used there
are two completely separate copies of the memory manager because...

> As far as I know, the initialization entry point is called automatically.
> But the compiler experts should confirm this. IIRC the behaviour changed
> as the support for libraries improved;

..(pending comment from compiler experts) there are completely separate
trees of units in the main program and each dynamically-loaded library.
The OS calls the initialisation block(s) for each library, and then
finally calls the initialisation block for the main program. So in the
context of one particular library, code in the main library
initialisation block should have a similar standing to that in the main
program initialisation block: everything else in that context (i.e. in
the library or in the main program) has been initialised before it is
called, and when it exits it goes back to the OS (possibly via
finalisation blocks).

--
Mark Morgan Lloyd
markMLl .AT. telemetry.co .DOT. uk

[Opinions above are the author's, not those of his employers or colleagues]
_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: Reproducible code: DLL calling Firebird crashes

Sven Barth-2

Am 30.09.2014 15:07 schrieb "Mark Morgan Lloyd" <[hidden email]>:
>> As far as I know, the initialization entry point is called automatically.
>> But the compiler experts should confirm this. IIRC the behaviour changed as the support for libraries improved;
>
>
> ..(pending comment from compiler experts) there are completely separate trees of units in the main program and each dynamically-loaded library. The OS calls the initialisation block(s) for each library, and then finally calls the initialisation block for the main program. So in the context of one particular library, code in the main library initialisation block should have a similar standing to that in the main program initialisation block: everything else in that context (i.e. in the library or in the main program) has been initialised before it is called, and when it exits it goes back to the OS (possibly via finalisation blocks).

It is indeed true that all units are initialized once the main code block of the library is called, but you are still inside the library initialization initiated by the OS and thus you are subject to its restrictions which in the case of Windows includes not to load any libraries there.

Regards,
Sven


_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: Reproducible code: DLL calling Firebird crashes

Marco van de Voort
In our previous episode, Sven Barth said:
> It is indeed true that all units are initialized once the main code block
> of the library is called, but you are still inside the library
> initialization initiated by the OS and thus you are subject to its
> restrictions which in the case of Windows includes not to load any
> libraries there.

So the obvious question might be if the unit initialization really  belongs
into the library initialization like that.
_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: Reproducible code: DLL calling Firebird crashes

Sven Barth-2
On 30.09.2014 20:17, Marco van de Voort wrote:
> In our previous episode, Sven Barth said:
>> It is indeed true that all units are initialized once the main code block
>> of the library is called, but you are still inside the library
>> initialization initiated by the OS and thus you are subject to its
>> restrictions which in the case of Windows includes not to load any
>> libraries there.
>
> So the obvious question might be if the unit initialization really  belongs
> into the library initialization like that.

The only other alternative would be to add the RTL initialization code
to each exported function. I don't consider this a viable alternative.

Note: Dynamic packages won't have this problem, because:
- for packages linked at compile time the initialization is run as part
of the program initialization AFTER the OS has initialized the library
(which doesn't do much in case of a package)
- for packages loaded at runtime it's done as part of the LoadPackage call
That's however only possible, because dynamic packages are very
different from simple libraries (and stuffed with compiler magic).

Regards,
Sven
_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: Reproducible code: DLL calling Firebird crashes

Mark Morgan Lloyd-5
In reply to this post by Marco van de Voort
Marco van de Voort wrote:
> In our previous episode, Sven Barth said:
>> It is indeed true that all units are initialized once the main code block
>> of the library is called, but you are still inside the library
>> initialization initiated by the OS and thus you are subject to its
>> restrictions which in the case of Windows includes not to load any
>> libraries there.
>
> So the obvious question might be if the unit initialization really  belongs
> into the library initialization like that.

Assuming that e.g. connecting to a database uses the Dynlibs unit, is
there any way that this could recognise that it was being invoked from
DLL/so initialisation code and raise a "don't try that here" exception?

Reinier: did you get as far as looking in Dynlibs for an error message
immediately after trying to connect to the database?

--
Mark Morgan Lloyd
markMLl .AT. telemetry.co .DOT. uk

[Opinions above are the author's, not those of his employers or colleagues]
_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: Reproducible code: DLL calling Firebird crashes

Mark Morgan Lloyd-5
In reply to this post by Sven Barth-2
Sven Barth wrote:

> The only other alternative would be to add the RTL initialization code
> to each exported function. I don't consider this a viable alternative.

Which is more or less what Reinier's working code did. I'd hate that to
be an implicit default.

> Note: Dynamic packages won't have this problem, because:
> - for packages linked at compile time the initialization is run as part
> of the program initialization AFTER the OS has initialized the library
> (which doesn't do much in case of a package)
> - for packages loaded at runtime it's done as part of the LoadPackage call
> That's however only possible, because dynamic packages are very
> different from simple libraries (and stuffed with compiler magic).

Is it possible for code in a unit to determine what sort of project it's
part of, i.e. a standalone program, a library etc.? Could the RTL have a
flag indicating that initialisation (or finalisation?) blocks were
currently being run, and anything called should assume that facilities
were restricted?

--
Mark Morgan Lloyd
markMLl .AT. telemetry.co .DOT. uk

[Opinions above are the author's, not those of his employers or colleagues]
_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
12