You are viewing a plain text version of this content. The canonical link for it is here.
Posted to modules-dev@httpd.apache.org by Andrej van der Zee <an...@gmail.com> on 2008/09/09 16:10:11 UTC

apr_open_file and apr_write_file in post_read_request and log_transaction

Hi,

I am new to Apache modules and I am trying to open a file in the hook
post_read_request and write to the file in log_transaction. The file
is supposed to be only valid for the duration of the request and is
named with a unique identifier (created by mod_unique_id). The
apr_file_t is carried, with other data, in the configuration vector
(request_config) between the different hooks. In post_read_reqeust I
open it like this (req_cfg is the configuration vector
request_config):

    req_cfg->log_file = NULL;
    req_cfg->filepath = (char*) apr_pstrcat(r->pool, path_name,
unique_id, NULL);
    apr_int32_t flags = APR_WRITE | APR_CREATE | APR_EXCL | APR_APPEND;
    rv = apr_file_open(&req_cfg->log_file, req_cfg->filepath, flags,
APR_OS_DEFAULT, r->pool);
    if (rv != APR_SUCCESS || req_cfg->log_file == NULL) {
       ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL, "Failed to create
resource log file: %s",
                                   req_cfg->filepath);
       return DECLINED;
  }

After this I am able to write to the file in this hook function. But,
when I try to write to the file in the hook log_transaction like this:

    char *msg = (char*) apr_psprintf(r->pool, "%s", "some msg");
    len = strlen(msg);
    apr_file_write(req_cfg->log_file, msg, &len);

Then I get a segfault because req_cfg->log_file is NULL. Here the
output from gdb:

Core was generated by `/usr/local/apache2/bin/httpd -k start'.
Program terminated with signal 11, Segmentation fault.
[New process 16759]
#0  apr_file_write (thefile=0x0, buf=0x81841d0, nbytes=0xbf8e5d94) at
file_io/unix/readwrite.c:151
151	    if (thefile->buffered) {
(gdb) print thefile
$1 = (apr_file_t *) 0x0
(gdb) Quit

Because the file is opened with r->pool (with r request_rec) in
post_read_request I expect it to be open in the hook log_transaction.
So I guess I am wrong? Is it closed by the cleanup handlers? And if
so, what is the way to make sure it is still open?

Cheers,
Andrej

Re: apr_open_file and apr_write_file in post_read_request and log_transaction

Posted by Sorin Manolache <so...@gmail.com>.
On Tue, Sep 9, 2008 at 17:21, Andrej van der Zee
<an...@gmail.com> wrote:
>> Maybe you fail to open the file and the error is not logged correctly.
> Write
>>
>> ap_log_error(APLOG_MARK, APLOG_ERR, 0, r->server, "Failed to create
>> resource log file: %s", req_cfg->filepath);
>>
>> instead of
>>
>> ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL, "Failed to create
>> resource log file: %s", req_cfg->filepath);
>
> What is the difference if I use r->server?

If the the server_rec * parameter of ap_log_error is null then the
message is logged to stderr_log. I am not sure if stderr_log is the
stderr file descriptor or if apache redirects it to something else.
When I test with NULL I don't get the message in my log file. You can
look at server/log.c, the log_error_core function, in the sources of
apache.

--
S

Re: apr_open_file and apr_write_file in post_read_request and log_transaction

Posted by Andrej van der Zee <an...@gmail.com>.
Hi,

Thanks for your reply.

I found that I memset() the req_cfg to 0 *after *I open the file. I am sorry
for wasting your time.... Anyway, please read on for more comments....

>
> Maybe you fail to open the file and the error is not logged correctly.
Write
>
> ap_log_error(APLOG_MARK, APLOG_ERR, 0, r->server, "Failed to create
> resource log file: %s", req_cfg->filepath);
>
> instead of
>
> ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL, "Failed to create
> resource log file: %s", req_cfg->filepath);

What is the difference if I use r->server?

> Slightly off-topic, I think creating a file, writing to it, and
> closing it for each request is not an efficient solution. Can't you
> open just one single log file once for the whole server (in
> post_config for example), generate the unique id in post_read, put the
> ID in the request notes (the "notes" field of the request_rec
> structure) and then use it in log_transaction?

I am aware of this. The thing is that in my specific case a forked CGI
process will also write to the same file. If I use a unique file for every
request I am sure that I don't get scrambled eggs. If you know a better
solution, please tell me. Note, my module will not run in production
environments, its more a debugging module...

Cheers,
Andrej

Re: apr_open_file and apr_write_file in post_read_request and log_transaction

Posted by Sorin Manolache <so...@gmail.com>.
On Tue, Sep 9, 2008 at 16:10, Andrej van der Zee
<an...@gmail.com> wrote:
> Hi,
>
> I am new to Apache modules and I am trying to open a file in the hook
> post_read_request and write to the file in log_transaction. The file
> is supposed to be only valid for the duration of the request and is
> named with a unique identifier (created by mod_unique_id). The
> apr_file_t is carried, with other data, in the configuration vector
> (request_config) between the different hooks. In post_read_reqeust I
> open it like this (req_cfg is the configuration vector
> request_config):
>
>    req_cfg->log_file = NULL;
>    req_cfg->filepath = (char*) apr_pstrcat(r->pool, path_name,
> unique_id, NULL);
>    apr_int32_t flags = APR_WRITE | APR_CREATE | APR_EXCL | APR_APPEND;
>    rv = apr_file_open(&req_cfg->log_file, req_cfg->filepath, flags,
> APR_OS_DEFAULT, r->pool);
>    if (rv != APR_SUCCESS || req_cfg->log_file == NULL) {
>       ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL, "Failed to create
> resource log file: %s",
>                                   req_cfg->filepath);
>       return DECLINED;
>  }
>
> After this I am able to write to the file in this hook function. But,
> when I try to write to the file in the hook log_transaction like this:
>
>    char *msg = (char*) apr_psprintf(r->pool, "%s", "some msg");
>    len = strlen(msg);
>    apr_file_write(req_cfg->log_file, msg, &len);
>
> Then I get a segfault because req_cfg->log_file is NULL. Here the
> output from gdb:
>
> Core was generated by `/usr/local/apache2/bin/httpd -k start'.
> Program terminated with signal 11, Segmentation fault.
> [New process 16759]
> #0  apr_file_write (thefile=0x0, buf=0x81841d0, nbytes=0xbf8e5d94) at
> file_io/unix/readwrite.c:151
> 151         if (thefile->buffered) {
> (gdb) print thefile
> $1 = (apr_file_t *) 0x0
> (gdb) Quit
>
> Because the file is opened with r->pool (with r request_rec) in
> post_read_request I expect it to be open in the hook log_transaction.
> So I guess I am wrong? Is it closed by the cleanup handlers? And if
> so, what is the way to make sure it is still open?
>
> Cheers,
> Andrej
>

I've more or less replicated your code and everything goes fine. The
difference is that I don't use unique_id but I hard-code the path in
the call to apr_file_open and I do not use APR_EXCL.

Maybe you fail to open the file and the error is not logged correctly. Write

ap_log_error(APLOG_MARK, APLOG_ERR, 0, r->server, "Failed to create
resource log file: %s", req_cfg->filepath);

instead of

ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL, "Failed to create
resource log file: %s", req_cfg->filepath);


Slightly off-topic, I think creating a file, writing to it, and
closing it for each request is not an efficient solution. Can't you
open just one single log file once for the whole server (in
post_config for example), generate the unique id in post_read, put the
ID in the request notes (the "notes" field of the request_rec
structure) and then use it in log_transaction?

S