I used to write apache modules in apache 1.3, but these days I am willing to pass to apache2. The module that I am writing at the moment has is own binary data, not a database, for performance purposes. I need to load this data in shared memory, so every child can access it without making his own copy, and it would be practical to load/create the binary data at startup, as I was used to do with apache 1.3. Problem is that I don't find an init event in apache2, in 1.3 in the module struct, immediatly after STANDARD_MODULE_STUFF you find a place for a /** module initializer */, in which you can put a function that will be executed early.
Body of the function I used to write is something like:
if ( getppid == 1 )
{
// Load global data here
// this is the parent process
void* data = loadGlobalData( someFilePath );
setGlobalData( config, data );
}
else
{
// this is the init of a child process
// do nothing
}
I am looking for a place in apache2 in where I can put a similar function.
Can you help?
Thanks
Benvenuto
Since you want the server to create a single shared memory segment to be used by all children, I would recommend initialising this in the post config hook (ap_hook_post_config). This is called once the configuration has been read, but before the children are spawned, so it should work well.
Since Apache 2.x loads DSO modules twice, ap_hook_post_config() is called twice during Apache startup.
The following code added to the ap_hook_post_config() will prevent the initialization of your module during the first call and continue only during the second call.
This is a hack, but a neat hack :)
void *data = NULL;
const char *key = "dummy_post_config";
// This code is used to prevent double initialization of the module during Apache startup
apr_pool_userdata_get(&data, key, s->process->pool);
if ( data == NULL ) {
apr_pool_userdata_set((const void *)1, key, apr_pool_cleanup_null, s->process->pool);
return OK;
}
You can read more about double dso module loads on the Apache wiki.
You can use a child_init hook to initialize a resource that will last longer then request or connection.
typedef struct {
apr_pool_t *pool;
apr_hash_t *hash;
} my_server_config;
static void my_child_init(apr_pool_t *p, server_rec *s)
{
my_server_config cfg = ap_get_module_config(s->module_config, &my_module);
/* Create sub-pool: ap_pool_create(&cfg->pool, p); */
/* Create hash: cfg->hash = ap_hash_make(cfg->pool); */
}
static void my_register_hooks(apr_pool_t *p)
{
ap_hook_child_init(my_child_init, NULL, NULL, APR_HOOK_MIDDLE);
}
module AP_MODULE_DECLARE_DATA my_module =
{
STANDARD20_MODULE_STUFF,
NULL, /* per-directory config creator */
NULL, /* dir config merger */
NULL, /* server config creator */
NULL, /* server config merger */
NULL, /* command table */
my_register_hooks, /* set up other request processing hooks */
};
Child init hook will be called before apache enters operational mode or before threads are created in threaded MPM. The pool passed into the my_child_init function should be process pool.
For better example you should download apache source code and check the modules/experimental/mod_example.c file.
Related
I have to implement a function that installs a new kernel extension in the system. Before installing the extension I want to check whether it is already installed from another location. Since I do not know the other location I cannot use the sysconfig library function.
I've checked
truss genkex
to see how this is done by another tool. The only system call that was a bit interesting was read_sysconfig. Unfortunately I did not find documentation.
Any ideas?
Here I have an example function, that prints all loaded kernel extensions:
#define BUFF_SIZE 10241024U
static void testExtension() {
void *buffer = calloc( 1, BUFF_SIZE );
if( buffer ) {
struct ld_info *xInfo;
int result = loadquery(L_GETKERNINFO, buffer, BUFF_SIZE);
xInfo = buffer;
while( xInfo ) {
printf( ">>>>>>> >%s< %d\n", xInfo->ldinfo_filename, result );
uint offset = xInfo->ldinfo_next;
xInfo = offset ? (char*)xInfo + offset : NULL;
}
free( buffer );
}
}
The function you search for is SYS_QUERYLOAD sysconfig operation and here you can find more information about it
The SYS_QUERYLOAD sysconfig operation performs a query operation to
determine if a given object file has been loaded. This object file is
specified by the path field in the cfg_load structure passed in with
the parmp parameter. This operation utilizes the same cfg_load
structure that is specified for the SYS_KLOAD (SYS_KLOAD sysconfig
Operation) operation.
If the specified object file is not loaded, the kmid field in the
cfg_load structure is set to a value of 0 on return. Otherwise, the
kernel module ID of the module is returned in the kmid field. If
multiple instances of the module have been loaded into the kernel, the
module ID of the one most recently loaded is returned.
The libpath field in the cfg_load structure is not used for this
option.
Also you can check with this script about the objects in odm database.
for i in 1 2 3
do
odmget -q phase=$i Config_Rules
done
And check the file /sbin/rc.boot (which may contain load of some module(s)
I have a few datamodules, created with C++ Builder 6. Each of them uses another datamodule that initializes the connection with the database. I'm trying to make a DLL out of those datamodules.
The error is thrown on creation of DataModule_Users and says 'Abnormal program termination'.
Where do I go wrong?
Thanks in advance
datamodule_dll.bpf
USEFORM("DataModule_Connection.cpp", DataModule_Connection); /* TDataModule: File Type */
USEFORM("DataModule_Users.cpp", DataModule_Users); /*TDataModule: File Type */
//------------------------------------------------------------------
This file is used by the project manager only and should be treated like the project file
DllEntryPoint
datamodule_DLL.cpp
int WINAPI DllEntryPoint(HINSTANCE hinst, unsigned long reason, void* lpReserved)
{
return 1;
}
extern "C" __declspec(dllexport) const char * GetUserName(const char * ID);
const char * GetUserName(const char * ID) {
CoInitialize(NULL); // datasets use COM
// This is used by DataModule_Users (normally this is done with Application->CreateForm();
DataModule_Connection = new DataModule_Connection( 0 /* Owner */ );
DataModule_Users = new DataModule_Users( 0 /* Owner */ );
return DataModule_Users->GetUserName(ID);
}
I will quote Remy Lebeau:
COM is initialized on a per-thread basis. Once a thread's COM model
(apartment vs multithreaded) has been set, it cannot be changed later.
If your DLL calls CoInitialize() before the caller does, your
parameters would take priority, which might not meet the caller's
needs. If you want to control the COM settings for your DMs without
affecting the caller, you have to move the DMs to their own thread.
Besides, DllEntryPoint() is not an appropriate place to initialize
them anyway. The OS restricts what DllEntryPoint() is allowed to do.
This solved the issue. I had to call coInitialize() before I load the library.
I wrote the module code like this:
static void *example_create_server_config(apr_pool_t *p, server_rec *s)
{
syslog(LOG_ERR, "create_server_config");
// create my handler
// my_handler_t *handler = (my_handler_t *)apr_palloc(pool, sizeof(my_handler_t));
return NULL;
}
/* Dispatch list for API hooks */
module AP_MODULE_DECLARE_DATA example_module = {
STANDARD20_MODULE_STUFF,
NULL, /* create per-dir config structures */
NULL, /* merge per-dir config structures */
example_create_server_config, /* create per-server config structures */
NULL, /* merge per-server config structures */
example_cmds, /* table of config file commands */
example_register_hooks /* register hooks */
};
When I restart Apache, the /var/log/syslog contains this:
Jan 31 14:46:49 su02 apache2: create_server_config
Jan 31 14:46:49 su02 apache2: create_server_config
Jan 31 14:46:49 su02 apache2: child_init
Why is the create_server_config function be called twice?
I malloc some global variables in this function. Is that safe or not?
It is perfectly safe to acquire memory using the apr_pool_t pointer that you receive inside of this function. Also, this function will be invoked once for every server/host configuration you have in your httpd.conf file, so that's why you see multiple calls to this function. For example a root server configuration and one configuration section would make this function be invoked twice.
typedef struct
{
int value;
} my_srv_cfg;
static void *example_create_server_config(apr_pool_t *pool, server_rec *s)
{
my_srv_cfg *new = apr_pcalloc(pool, sizeof (*new));
new->value = 100;
return new;
}
I've been coding an NGINX filter module that can read/write cookies for incoming requests. If a particular cookie isn't set correctly (i.e. authentication cookie), it will set the outgoing header status to the appropriate error code. This works fine per the directions of Evan Miller's tutorial. The next part I'm trying to get working (and haven't thus far) is having the body filter be invoked so I can insert/replace body response text when error responses are encountered. I again followed Evan Miller's tutorial on body filters, and I cannot for the life of me get this working. Here's my setup:
static ngx_http_output_header_filter_pt ngx_http_next_header_filter;
static ngx_http_output_body_filter_pt ngx_http_next_body_filter;
...
...
static ngx_http_module_t ngx_http_source_cookie_module_ctx = {
NULL, /* preconfiguration */
ngx_http_source_cookie_init, /* postconfiguration */
NULL, /* create main configuration */
NULL, /* init main configuration */
NULL, /* create server configuration */
NULL, /* merge server configuration */
ngx_http_source_cookie_create_loc_conf, /* create location configuration */
ngx_http_source_cookie_merge_loc_conf /* merge location configuration */
};
ngx_module_t ngx_http_source_cookie_module = {
NGX_MODULE_V1,
&ngx_http_source_cookie_module_ctx, /* module context */
ngx_http_source_cookie_commands, /* module directives */
NGX_HTTP_MODULE, /* module type */
NULL, /* init master */
NULL, /* init module */
NULL, /* init process */
NULL, /* init thread */
NULL, /* exit thread */
NULL, /* exit process */
NULL, /* exit master */
NGX_MODULE_V1_PADDING
};
/*--------------------------------------------------------------------------*/
/*--------------------------------------------------------------------------*/
static ngx_int_t
ngx_http_source_cookie_header_filter(ngx_http_request_t *r)
{
// this gets invoked
...
}
/*--------------------------------------------------------------------------*/
/*--------------------------------------------------------------------------*/
static ngx_int_t
ngx_http_body_filter(ngx_http_request_t *r, ngx_chain_t *in)
{
// this never get invoked
...
}
/*--------------------------------------------------------------------------*/
/*--------------------------------------------------------------------------*/
static ngx_int_t
ngx_http_source_cookie_init(ngx_conf_t *cf)
{
// registering of my filters
ngx_http_next_header_filter = ngx_http_top_header_filter;
ngx_http_top_header_filter = ngx_http_source_cookie_header_filter;
ngx_http_next_body_filter = ngx_http_top_body_filter;
ngx_http_top_body_filter = ngx_http_body_filter;
return NGX_OK;
}
This is my basic setup, and as far as I can tell, it's spot on all the examples/tutorials I've come across. I'm wondering if there's something different altogether I need to enable... like a NGINX config option, NGINX ./configure compile option, etc.
Any help is greatly appreciated.
I note that Evan doesnt fix http content length in ngx_http_<module_name>_header_filter().
If I dont add http content length(r->headers_out.content_length_n), the inserted text to the end of request will not be output from nginx-1.2.7 stable.
Also you can see footer filter module.
I want to write a little Linux Kernel Module that can show me the PID of all running processes.
I have the following code:
/*
* procInfo.c My Kernel Module for process info
*/
#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>
/*
* The init function, called when the module is loaded.
* Returns zero if successfully loaded, nonzero otherwise.
*/
static int mod_init(void)
{
printk(KERN_ALERT "ProcInfo sucessfully loaded.\n");
return 0;
}
/*
* The exit function, called when the module is removed.
*/
static void mod_exit(void)
{
printk(KERN_ALERT "ProcInfo sucessfully unloaded.\n");
}
void getProcInfo()
{
printk(KERN_INFO "The process is \"%s\" (pid %i)\n",
current->comm, current->pid);
}
module_init(mod_init);
module_exit(mod_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Rodrigo");
As you can see, i know i have to use the *struct task_struct* structure to get the PID and the Process name, but i am using current, and i know the existance of some double linked circular list that contains all PCB's, so the main question is:
what do i need to add to iterate over this linked lisk with p-next_task and p-prev_task so getProcInfo works?
Thanks!
The following macros from include/linux/sched.h may be useful:
#define next_task(p) \
list_entry_rcu((p)->tasks.next, struct task_struct, tasks)
#define for_each_process(p) \
for (p = &init_task ; (p = next_task(p)) != &init_task ; )
You probably need to hold the tasklist_lock before calling these macros; several examples of how to lock, iterate, and unlock, are in mm/oom_kill.c.
Actually, for newer kernels (2.6.18 and newer) the proper way to list tasks is by holding an rcu lock, because task list is now an RCU list. Also tasklist_lock is no more exported symbol - it means that when you are compiling a loadable kernel module, this symbol will not be visible for you.
example code to use
struct task_struct *task;
rcu_read_lock();
for_each_process(task) {
task_lock(task);
/* do something with your task :) */
task_unlock(task);
}
rcu_read_unlock();
Also documentation about RCU in linux kernel source directory can be helpful and you will find it in Documentation/RCU