1

What is proper use of Apache method apr_pool_create_ex in Delphi XE?

I’ve created Apache modules before, but all were Handlers. Now I’m working on developing a Service provider. A skeleton module has been created and my child_init call back method is being called by Apache. In the child_init method I call ap_pool_create_ex* successfully (returns APR_SUCCESS), but after leaving the child_it call, I receive an access violation either during the (httpd.exe) spawning of the third or the fourth worker thread (third is showing in the event log).

procedure provider_child_init(pchild: Papr_pool_t; s: Pserver_rec); cdecl;
var
  rv  : apr_status_t;
  mypool : Papr_pool_t;
begin
  rv := -1;
  rv := apr_pool_create_ex(@mypool,pchild,nil,nil);
end;

The AV message is:

“Project C:\Apache2.2\bin\http.exe raised too many consecutive exceptions: ‘access violation at 0x00000000: read of address 0x00000000’. Process Stopped. Use Step or Run to continues”

Event Log:

…
Thread Start: Thread ID: 5652. Process httpd.exe (4212)
Thread Start: Thread ID: 5132. Process httpd.exe (4212)
Thread Start: Thread ID: 5988. Process httpd.exe (4212) 

NOTE: The AV occurs in Thread ID 5988 and 4212 is the Parent httpd.exe process.

  • The windows “libapr-1.dll” does not include “apr_pool_create”, that is why I’m using the “_ex” version. Any idea why apr_pool_create is missing? I see apr_pool_create being used in other successful modules although they are written in ‘C’.

OS: Windows 7 Enterprise 64-bit

Apache: 2.2.17.0

IDE: Delphi XE

David Heffernan
  • 601,492
  • 42
  • 1,072
  • 1,490
TDF
  • 125
  • 7
  • Regarding why apr_pool_create is missing, it's probably not exported from the DLL because anything you can do with it you can also do with apr_pool_create_ex, and more. Modules written in C can still link with it statically, though. – Ondrej Kelle Mar 26 '11 at 00:34

1 Answers1

2

Is your translation of the function correct? Delphi XE Version Insight (Subversion plugin) declares it as follows:

type
  PAprPool = ^TAprPool;
  TAprPool = THandle;
  PAprAllocator = ^TAprAllocator;
  TAprAllocator = THandle;
  TAprAbortFunc = function(retcode: Integer): Integer; stdcall;

var
  apr_pool_create_ex: function(out newpool: PAprPool; parent: PAprPool; abort_fn: TAprAbortFunc;
    allocator: PAprAllocator): TAprStatus; stdcall;

Also check if your provider_child_init callback should really be declared as cdecl and not stdcall.

Also, some ideas since you get a null pointer access violation. According to the apr source code comment:

  • if (as in your case) you pass it a nil allocator the allocator of the parent pool will be used. I assume that in case the parent pool is nil the allocator must not be nil.
  • abort_fn will be called back if the pool cannot allocate memory. You're passing it nil; perhaps the pool is trying to call it because it cannot allocate memory?
  • I don't think you can access the same pool from different threads. You probably have to create a separate pool for each thread.
Ondrej Kelle
  • 36,941
  • 2
  • 65
  • 128
  • Thanks for the help. I was using the FreePascal definition for apr_pool_create_ex (not included in Delphi). It seems that the first parameter was the culprit. I had an abort_fn defined but it wasn't being called so as part of attempting to make it work I set it to nil to see what would happen. BTW, the provider_child_init func is defined as cdecl. – TDF Mar 26 '11 at 02:13