Re: [fpc-pascal] Reproducible code: DLL calling Firebird crashes

2014-10-02 Thread Mark Morgan Lloyd

Reinier Olislagers wrote:

On 30/09/2014 22:05, Mark Morgan Lloyd wrote:

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

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


No, I didn't.


Assuming you've got = 2.6.2, modify your code to look like this:

uses DynLibs;
..
  WriteLn('Before TDBInterface.Create(): ', GetLoadErrorStr);
  DBLayer:=TDBInterface.Create;
  WriteLn('After TDBInterface.Create(): ', GetLoadErrorStr);

On Linux, I can see it calling the database connection stuff but then it 
raises an exception because it can't find the named server etc. So at 
least on Linux it's apparently transferring control into the 
demand-loaded database stuff, since otherwise there wouldn't be the 
messages as shown below. Whether it's appropriate and portable to do it 
like that is a different issue.


I don't want to have to spend time changing your test code to suit 
PostgreSQL or digging out names etc. for the limited number of Firebird 
databases I've got set up, and I /really/ don't want to start fiddling 
with Windows.


Before TDBInterface.Create():
An unhandled exception occurred at $B767EFEF :
EIBDatabaseError :  : DoInternalConnect :
 -Unable to complete network request to host firebirdserver.
 -Failed to locate host machine.

--
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  -  fpc-pascal@lists.freepascal.org
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal


Re: [fpc-pascal] Reproducible code: DLL calling Firebird crashes

2014-10-02 Thread Reinier Olislagers
On 02/10/2014 12:19, Mark Morgan Lloyd wrote:
 Reinier Olislagers wrote:
 On 30/09/2014 22:05, Mark Morgan Lloyd wrote:
 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
 Reinier: did you get as far as looking in Dynlibs for an error message
 immediately after trying to connect to the database?

 No, I didn't.
 
 Assuming you've got = 2.6.2, modify your code to look like this:

Sorry to be a bit abrupt here but I'm not really interested in tweaking
this either. I've submitted a bug report which was closed. If anybody
else wants to look into this, fine by me, but I won't spend any more
time on it.

Some background: if I'm using e.g. FPC-provided units that just happen
to load dlls dynamically (such as sqldb but probably also others) I, as
a programmer, do not necessarily know or want to know that
implementation detail. Rather than messing with havint to adapt code for
those scenarios I'll just not use the initalization sections at all as I
documented on the wiki.

Thanks for all the help.

___
fpc-pascal maillist  -  fpc-pascal@lists.freepascal.org
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal


Re: [fpc-pascal] Reproducible code: DLL calling Firebird crashes

2014-10-02 Thread Michael Van Canneyt



On Thu, 2 Oct 2014, Reinier Olislagers wrote:


On 02/10/2014 12:19, Mark Morgan Lloyd wrote:

Reinier Olislagers wrote:

On 30/09/2014 22:05, Mark Morgan Lloyd wrote:

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

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


No, I didn't.


Assuming you've got = 2.6.2, modify your code to look like this:


Sorry to be a bit abrupt here but I'm not really interested in tweaking
this either. I've submitted a bug report which was closed. If anybody
else wants to look into this, fine by me, but I won't spend any more
time on it.

Some background: if I'm using e.g. FPC-provided units that just happen
to load dlls dynamically (such as sqldb but probably also others) I, as
a programmer, do not necessarily know or want to know that
implementation detail. Rather than messing with havint to adapt code for
those scenarios I'll just not use the initalization sections at all as I
documented on the wiki.


That is my conclusion since ages: I don't use initialization sections,
except maybe to initialize a variable.

You quickly learn this when you need to debug e.g. windows services.

Michael.
___
fpc-pascal maillist  -  fpc-pascal@lists.freepascal.org
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal


Re: [fpc-pascal] Reproducible code: DLL calling Firebird crashes

2014-10-01 Thread Marco van de Voort
In our previous episode, Sven Barth said:
  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.

Simpler, for manual managed DLLs, you need to manually call an initialization 
and
finalization. Period.
 
___
fpc-pascal maillist  -  fpc-pascal@lists.freepascal.org
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal


Re: [fpc-pascal] Reproducible code: DLL calling Firebird crashes

2014-09-30 Thread 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  -  fpc-pascal@lists.freepascal.org
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal


Re: [fpc-pascal] Reproducible code: DLL calling Firebird crashes

2014-09-30 Thread Mark Morgan Lloyd

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  -  fpc-pascal@lists.freepascal.org
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal


Re: [fpc-pascal] Reproducible code: DLL calling Firebird crashes

2014-09-30 Thread 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  -  fpc-pascal@lists.freepascal.org
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal


Re: [fpc-pascal] Reproducible code: DLL calling Firebird crashes

2014-09-30 Thread Mark Morgan Lloyd

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  -  fpc-pascal@lists.freepascal.org
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal


Re: [fpc-pascal] Reproducible code: DLL calling Firebird crashes

2014-09-30 Thread 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  -  fpc-pascal@lists.freepascal.org
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal


Re: [fpc-pascal] Reproducible code: DLL calling Firebird crashes

2014-09-30 Thread Mark Morgan Lloyd

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  -  fpc-pascal@lists.freepascal.org
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal


Re: [fpc-pascal] Reproducible code: DLL calling Firebird crashes

2014-09-30 Thread Sven Barth
Am 30.09.2014 15:07 schrieb Mark Morgan Lloyd 
markmll.fpc-pas...@telemetry.co.uk:
 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  -  fpc-pascal@lists.freepascal.org
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal

Re: [fpc-pascal] Reproducible code: DLL calling Firebird crashes

2014-09-30 Thread 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  -  fpc-pascal@lists.freepascal.org
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal


Re: [fpc-pascal] Reproducible code: DLL calling Firebird crashes

2014-09-30 Thread Sven Barth

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  -  fpc-pascal@lists.freepascal.org
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal


Re: [fpc-pascal] Reproducible code: DLL calling Firebird crashes

2014-09-30 Thread Mark Morgan Lloyd

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  -  fpc-pascal@lists.freepascal.org
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal


Re: [fpc-pascal] Reproducible code: DLL calling Firebird crashes

2014-09-30 Thread Mark Morgan Lloyd

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  -  fpc-pascal@lists.freepascal.org
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal


Re: [fpc-pascal] Reproducible code: DLL calling Firebird crashes

2014-09-30 Thread Reinier Olislagers
On 30/09/2014 22:05, Mark Morgan Lloyd wrote:
 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
 Reinier: did you get as far as looking in Dynlibs for an error message
 immediately after trying to connect to the database?

No, I didn't.


___
fpc-pascal maillist  -  fpc-pascal@lists.freepascal.org
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal


Re: [fpc-pascal] Reproducible code: DLL calling Firebird crashes

2014-09-29 Thread Mark Morgan Lloyd

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  -  fpc-pascal@lists.freepascal.org
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal


Re: [fpc-pascal] Reproducible code: DLL calling Firebird crashes

2014-09-29 Thread 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  -  fpc-pascal@lists.freepascal.org
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal


Re: [fpc-pascal] Reproducible code: DLL calling Firebird crashes

2014-09-29 Thread Reinier Olislagers
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  -  fpc-pascal@lists.freepascal.org
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal


Re: [fpc-pascal] Reproducible code: DLL calling Firebird crashes

2014-09-29 Thread José Mejuto

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  -  fpc-pascal@lists.freepascal.org
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal


Re: [fpc-pascal] Reproducible code: DLL calling Firebird crashes

2014-09-29 Thread 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  -  fpc-pascal@lists.freepascal.org
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal


Re: [fpc-pascal] Reproducible code: DLL calling Firebird crashes

2014-09-29 Thread Mark Morgan Lloyd

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  -  fpc-pascal@lists.freepascal.org
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal


Re: [fpc-pascal] Reproducible code: DLL calling Firebird crashes

2014-09-29 Thread 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  -  fpc-pascal@lists.freepascal.org
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal


Re: [fpc-pascal] Reproducible code: DLL calling Firebird crashes

2014-09-29 Thread Mark Morgan Lloyd

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  -  fpc-pascal@lists.freepascal.org
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal