Crash in apr_file_close() (Linux)

View: New views
20 Messages — Rating Filter:   Alert me  
< Prev | 1 - 2 | Next >

Crash in apr_file_close() (Linux)

by Yuri V. Vishnevskiy :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Dear developers,
For some reason in my program I need two file handlers of stdout stream.
When I close these handlers I obtain an error on the second close: "Bad  
file descriptor"

Here is the simple testcase code:


#include <stdlib.h>
#include <stdio.h>
#include "apr.h"
#include "apr_pools.h"
#include "apr_file_io.h"

int main(int a, char** b)
{
apr_pool_t * pool;
apr_file_t *file1, *file2;
apr_status_t status;
char errbuf[100];


  apr_initialize();
  apr_pool_create(&pool, NULL);

  apr_file_open_stdout(&file1, pool);
  apr_file_open_stdout(&file2, pool);

  apr_file_puts("Hello World (1)\n", file1);
  apr_file_puts("Hello World (2)\n", file2);

  status = apr_file_close(file1);
  if(status!=APR_SUCCESS) {
    apr_strerror(status, errbuf, sizeof(errbuf));
    fprintf(stderr, "file1 close error:  %s\n", errbuf);
  }

  status = apr_file_close(file2); // <--- returns non-APR_SUCCESS
  if(status!=APR_SUCCESS) {
    apr_strerror(status, errbuf, sizeof(errbuf));
    fprintf(stderr, "file2 close error:  %s\n", errbuf);
  }

  apr_terminate();

  return(0);
}


Could anybody try to reproduce this problem?
If it really exists, should it be fixed in APR or it is my problem to  
handle such things?

I use APR 1.3.8
My system is Linux Debian Squeeze, x86_64.

Regards,
Yura Vishnevskiy

Re: Crash in apr_file_close() (Linux)

by Bojan Smojver :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

On Fri, 2009-10-16 at 15:26 +0700, Yuri V. Vishnevskiy wrote:
> For some reason in my program I need two file handlers of stdout
> stream.

If you duplicate the descriptor with apr_file_dup() instead of calling
apr_file_open_stdout() twice, does it still do the same?

--
Bojan


Re: Crash in apr_file_close() (Linux)

by Joe Orton :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

On Fri, Oct 16, 2009 at 03:26:31PM +0700, Yuri V. Vishnevskiy wrote:
> Dear developers,
> For some reason in my program I need two file handlers of stdout stream.
> When I close these handlers I obtain an error on the second close: "Bad  
> file descriptor"

It seems like reasonable behaviour that the second apr_file_close() call
should fail, though it certainly isn't obvious from reading the docs.  
How else do you expect it to behave?  You cannot close an fd twice.

If you want to be able to close the fds without closing stdout, then use
apr_file_dup() to create the second handle to stdout.

Regards, Joe


Re: Crash in apr_file_close() (Linux)

by mturk :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

On 16/10/09 10:26, Yuri V. Vishnevskiy wrote:
> Dear developers,
> For some reason in my program I need two file handlers of stdout stream.
>
> Could anybody try to reproduce this problem?

Crash happens on windows as well, so it might be a real
thing.
If you need two file objects perhaps a dup could help.
Anyhow crash should not happen or at least we should
not that opening stdsream twice could make a crash.


Regards
--
^TM


Re: Crash in apr_file_close() (Linux)

by Yuri V. Vishnevskiy :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

> On Fri, 2009-10-16 at 15:26 +0700, Yuri V. Vishnevskiy wrote:
>> For some reason in my program I need two file handlers of stdout
>> stream.
>
> If you duplicate the descriptor with apr_file_dup() instead of calling
> apr_file_open_stdout() twice, does it still do the same?
>


With apr_file_dup() everything is fine, no errors.


Re: Crash in apr_file_close() (Linux)

by mturk :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

On 16/10/09 10:39, Joe Orton wrote:
>
> It seems like reasonable behaviour that the second apr_file_close() call
> should fail, though it certainly isn't obvious from reading the docs.
> How else do you expect it to behave?  You cannot close an fd twice.
>

I suppose it shouldn't crash the apr.
IMO either second call to open should fail or
the call to close should fail, but without actually calling the close().

Regards
--
^TM


Re: Crash in apr_file_close() (Linux)

by Joe Orton :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

On Fri, Oct 16, 2009 at 10:54:13AM +0200, Mladen Turk wrote:

> On 16/10/09 10:39, Joe Orton wrote:
>>
>> It seems like reasonable behaviour that the second apr_file_close() call
>> should fail, though it certainly isn't obvious from reading the docs.
>> How else do you expect it to behave?  You cannot close an fd twice.
>>
>
> I suppose it shouldn't crash the apr.
> IMO either second call to open should fail or
> the call to close should fail, but without actually calling the close().

I think the reporter meant "fail" when they said "crash".

I don't see any reason why it would crash on Unix: the first call to
apr_file_close() will set fd->filedes to -1 after calling close(), the
second one will call close(-1) and fail with EBADF.

Regards, Joe

Re: Crash in apr_file_close() (Linux)

by mturk :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

On 16/10/09 11:01, Joe Orton wrote:
>
> I think the reporter meant "fail" when they said "crash".
>

Dunno what he meant but I confirmed last week's almost exact
report that crashes (really) windows.

> I don't see any reason why it would crash on Unix: the first call to
> apr_file_close() will set fd->filedes to -1 after calling close(), the
> second one will call close(-1) and fail with EBADF.
>

each invocation to apr_file_open_stdout creates a new apr_file_t so
each fd->filedes has a value of STDOUT_FILENO.
This is the same as calling:
close(1);
close(1);

This cores on Windows with latest MSVCRT, so it might crash
some Unix versions as well?

Regards
--
^TM


Re: Crash in apr_file_close() (Linux)

by Yuri V. Vishnevskiy :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message


> On Fri, Oct 16, 2009 at 10:54:13AM +0200, Mladen Turk wrote:
>> On 16/10/09 10:39, Joe Orton wrote:
>>>
>>> It seems like reasonable behaviour that the second apr_file_close()  
>>> call
>>> should fail, though it certainly isn't obvious from reading the docs.
>>> How else do you expect it to behave?  You cannot close an fd twice.
>>>
>>
>> I suppose it shouldn't crash the apr.
>> IMO either second call to open should fail or
>> the call to close should fail, but without actually calling the close().
>
> I think the reporter meant "fail" when they said "crash".
>
> I don't see any reason why it would crash on Unix: the first call to
> apr_file_close() will set fd->filedes to -1 after calling close(), the
> second one will call close(-1) and fail with EBADF.



I have two separate file descriptors. Second apr_file_close(file2) will  
fail even if file2->filedes==1.

So I understand that I have to handle such things by myself.

But if I can't close second handle why it is possible to open it  
successfully?

Regards,
Yura

Re: Crash in apr_file_close() (Linux)

by Joe Orton :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

On Fri, Oct 16, 2009 at 11:17:17AM +0200, Mladen Turk wrote:
> each invocation to apr_file_open_stdout creates a new apr_file_t so
> each fd->filedes has a value of STDOUT_FILENO.
> This is the same as calling:
> close(1);
> close(1);

Oh, good point.  This is rather horrible :(.  I'm not sure what can be
done about it, we can't change apr_file_open_stdout() to do a dup()
internally, since that would break existing apps.

Regards, Joe

Re: Crash in apr_file_close() (Linux)

by Yuri V. Vishnevskiy :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

On Fri, 16 Oct 2009 15:39:49 +0700, Joe Orton <jorton@...> wrote:

> On Fri, Oct 16, 2009 at 03:26:31PM +0700, Yuri V. Vishnevskiy wrote:
>> Dear developers,
>> For some reason in my program I need two file handlers of stdout stream.
>> When I close these handlers I obtain an error on the second close: "Bad
>> file descriptor"
>
> It seems like reasonable behaviour that the second apr_file_close() call
> should fail, though it certainly isn't obvious from reading the docs.
> How else do you expect it to behave?  You cannot close an fd twice.

I understand that very clearly. What I do not understand well is the APR  
file API policy, since apr_file_ functions are general for both usual  
files and std*.

Re: Crash in apr_file_close() (Linux)

by mturk :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

On 16/10/09 11:21, Joe Orton wrote:

> On Fri, Oct 16, 2009 at 11:17:17AM +0200, Mladen Turk wrote:
>> each invocation to apr_file_open_stdout creates a new apr_file_t so
>> each fd->filedes has a value of STDOUT_FILENO.
>> This is the same as calling:
>> close(1);
>> close(1);
>
> Oh, good point.  This is rather horrible :(.  I'm not sure what can be
> done about it, we can't change apr_file_open_stdout() to do a dup()
> internally, since that would break existing apps.
>

I'm not sure why do we call close(0..2) for std files when
the apr_file_open_std* is closed or it's pool destroyed at the
first place.

Reading the:
  * @remark The only reason that the apr_file_open_std* functions exist
  * is that you may not always have a stderr/out/in on Windows.  This
  * is generally a problem with newer versions of Windows and services.

So apr_file_open_std* should just reference the existing
system descriptors. However it behaves like 'attach' rather then open,
meaning once you open it you will destroy the system stdin/stdout/stderr.
Thus by design it's a singleton operation, so if desired,
the second invocation during the process lifetime should always
return EBADF for apr_file_open_std* thought.


Very confusing.


Regards
--
^TM


Re: Crash in apr_file_close() (Linux)

by Yuri V. Vishnevskiy :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

> I'm not sure why do we call close(0..2) for std files when
> the apr_file_open_std* is closed or it's pool destroyed at the
> first place.
>
> Reading the:
>   * @remark The only reason that the apr_file_open_std* functions exist
>   * is that you may not always have a stderr/out/in on Windows.  This
>   * is generally a problem with newer versions of Windows and services.
>
> So apr_file_open_std* should just reference the existing
> system descriptors. However it behaves like 'attach' rather then open,
> meaning once you open it you will destroy the system stdin/stdout/stderr.
> Thus by design it's a singleton operation, so if desired,
> the second invocation during the process lifetime should always
> return EBADF for apr_file_open_std* thought.
>
>
> Very confusing.

This is related with another my problem. If I close stdout by  
apr_file_close, then the standard printf and fprintf(stdout, ) functions  
are no more working.
I've tested this on Windows and Linux.

Regards,
Yura

Re: Crash in apr_file_close() (Linux)

by Jonathan Leffler-2 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message


On Fri, Oct 16, 2009 at 7:31 AM, Yuri V. Vishnevskiy <yuri.vishnevskiy@...> wrote:
This is related with another my problem. If I close stdout by apr_file_close, then the standard printf and fprintf(stdout, ) functions are no more working.
I've tested this on Windows and Linux.

If you close standard output, functions that write to standard output should not succeed - there is nowhere for the information to go.  That is (or, IMO, should be) expected behaviour.

--
Jonathan Leffler <jonathan.leffler@...>  #include <disclaimer.h>
Guardian of DBD::Informix - v2008.0513 - http://dbi.perl.org
"Blessed are we who can laugh at ourselves, for we shall never cease to be amused."

Re: Crash in apr_file_close() (Linux)

by mturk :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

On 16/10/09 16:41, Jonathan Leffler wrote:

>
> On Fri, Oct 16, 2009 at 7:31 AM, Yuri V. Vishnevskiy
> <yuri.vishnevskiy@... <mailto:yuri.vishnevskiy@...>> wrote:
>
>     This is related with another my problem. If I close stdout by
>     apr_file_close, then the standard printf and fprintf(stdout, )
>     functions are no more working.
>     I've tested this on Windows and Linux.
>
>
> If you close standard output, functions that write to standard output
> should not succeed - there is nowhere for the information to go.  That
> is (or, IMO, should be) expected behaviour.
>

What 99% users would need is apr_file_attach_std* set of functions
giving the apr_file_t capable API without destroying the system
std streams.

And we should probably protect the sigleton apr_file_open_std*
against multiple invocations, cause the always acts upon a
singleton std stream object.


Regards
--
^TM


Re: Crash in apr_file_close() (Linux)

by William A. Rowe Jr. :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Mladen Turk wrote:
>
> What 99% users would need is apr_file_attach_std* set of functions
> giving the apr_file_t capable API without destroying the system
> std streams.
>
> And we should probably protect the sigleton apr_file_open_std*
> against multiple invocations, cause the always acts upon a
> singleton std stream object.

We already have it.

Simply don't call close() :)

Just check if apr is registering closure of these streams and perhaps ensure
they are not closed at all if they are not overridden, certainly by apr 2.0.


Re: Crash in apr_file_close() (Linux)

by Yuri V. Vishnevskiy :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

>
> If you close standard output, functions that write to standard output  
> should
> not succeed - there is nowhere for the information to go.  That is (or,  
> IMO,
> should be) expected behaviour.

No doubt. Then how should I to use std* after apr_terminate()?


Re: Crash in apr_file_close() (Linux)

by William A. Rowe Jr. :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Yuri V. Vishnevskiy wrote:
>>
>> If you close standard output, functions that write to standard output
>> should
>> not succeed - there is nowhere for the information to go.  That is
>> (or, IMO,
>> should be) expected behaviour.
>
> No doubt. Then how should I to use std* after apr_terminate()?

Once you call apr_terminate(), all bets are off if you use such posix entities
of apr objects.  If apr_terminate() is closing the system-provided stdin/out/err,
that is something we can fix either in 1.x (if it is inconsistent/ill defined)
or 2.0 for certain.

Re: Crash in apr_file_close() (Linux)

by mturk :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

On 16/10/09 16:56, William A. Rowe, Jr. wrote:

> Mladen Turk wrote:
>>
>> What 99% users would need is apr_file_attach_std* set of functions
>> giving the apr_file_t capable API without destroying the system
>> std streams.
>>
>> And we should probably protect the sigleton apr_file_open_std*
>> against multiple invocations, cause the always acts upon a
>> singleton std stream object.
>
> We already have it.
>
> Simply don't call close() :)
>

Sure. However we should at least return EBADF on a second
invocation cause we know the first one will destroy stdout when
closed (directly, via pool destroy or via terminate)

For 2.0 apr_file_attach_std* might be a valuable addition
for repetitive apr_file_t objects allowing file API without
jeopardizing the stream integrity.


Regards
--
^TM


Re: Crash in apr_file_close() (Linux)

by William A. Rowe Jr. :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Mladen Turk wrote:

> On 16/10/09 16:56, William A. Rowe, Jr. wrote:
>> Mladen Turk wrote:
>>>
>>> What 99% users would need is apr_file_attach_std* set of functions
>>> giving the apr_file_t capable API without destroying the system
>>> std streams.
>>>
>>> And we should probably protect the sigleton apr_file_open_std*
>>> against multiple invocations, cause the always acts upon a
>>> singleton std stream object.
>>
>> We already have it.
>>
>> Simply don't call close() :)
>>
>
> Sure. However we should at least return EBADF on a second
> invocation cause we know the first one will destroy stdout when
> closed (directly, via pool destroy or via terminate)

apr_file_open_std* should not auto-close the underlying file stream ever,
only the apr_file_t pointer.

If apr_file_t is then dup'ed to a std* stream, then again all bets will be
off once apr_terminate is invoked.  Perhaps all will be well, but no assurance.

> For 2.0 apr_file_attach_std* might be a valuable addition
> for repetitive apr_file_t objects allowing file API without
> jeopardizing the stream integrity.

In 2.0, we can simply change such semantics.
< Prev | 1 - 2 | Next >