You are viewing a plain text version of this content. The canonical link for it is here.
Posted to users@subversion.apache.org by Davyd McColl <da...@gmail.com> on 2009/05/27 20:24:48 UTC

segfault at exit -- can anyone spot what I'm doing wrong?

Good day

I have some C++ code which uses the svn_fs_* functions. I've noticed a bit
of an oddity, and I'm hoping that someone can just tell me that I'm
forgetting to do something. It seems that when I try to perform functions on
dirs or files in the repo, if I specify a path that doesn't exist in the
repo, I don't just get failure for the called function -- I also get a
segfault in apr_terminate() when the last call is made to apr_terminate()
(as I understand it, the last call in a stack of apr_initalize()[*N*]
apr_terminate()[*N*] is the one called...

A simple code example:

    const char *szPath = "/";
    apr_initialize();
    apr_pool_t *pt = svn_pool_create(NULL);
    svn_fs_initialize(pt);
    svn_repos_t *repo;
    svn_repos_open(&repo, argv[REPO_ARG], pt);
    svn_fs_t *fs = svn_repos_fs(repo);
    svn_fs_root_t *root;
    svn_fs_revision_root(&root, fs, 1, pt);

    apr_pool_t *ptSub = svn_pool_create(pt);
    apr_hash_t *hash;
    svn_fs_dir_entries(&hash, root, szPath, ptSub);

    svn_pool_destroy(ptSub);
    svn_pool_destroy(pt);
    apr_terminate();
    return 0;

With szPath set to "/" as above, all works as expected and the application
exits cleanly. However, if szPath were set to a path not available in the
repo at the revision set (for example, if I set the path to "/foobar"), then
not only does the svn_fs_dir_entries() call fail (yes, I know I'm not
checking for the error here, but I know it does fail -- and I really
couldn't expect otherwise for a path not in the repo...), but when the time
comes for the apr_terminate() call, the application segfaults.

I'm using subversion-1.6.1, compiled from source on my own machine with
Visual Studio 2008. I'm assuming that there's some crucial step that I'm
missing out in the code above and would dearly appreciate any constructive
thoughts on the problem

-d


-- 
-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
Truth doesn't cease to be just because you don't agree with it.

------------------------------------------------------
http://subversion.tigris.org/ds/viewMessage.do?dsForumId=1065&dsMessageId=2355925

To unsubscribe from this discussion, e-mail: [users-unsubscribe@subversion.tigris.org].

Re: segfault at exit -- can anyone spot what I'm doing wrong?

Posted by "Hyrum K. Wright" <hy...@hyrumwright.org>.
On May 27, 2009, at 7:18 PM, Blair Zajac wrote:

> Hyrum K. Wright wrote:
>> On May 27, 2009, at 3:24 PM, Davyd McColl wrote:
>>> Good day
>>>
>>> I have some C++ code which uses the svn_fs_* functions. I've  
>>> noticed  a bit of an oddity, and I'm hoping that someone can just  
>>> tell me  that I'm forgetting to do something. It seems that when I  
>>> try to  perform functions on dirs or files in the repo, if I  
>>> specify a path  that doesn't exist in the repo, I don't just get  
>>> failure for the  called function -- I also get a segfault in  
>>> apr_terminate() when the  last call is made to apr_terminate() (as  
>>> I understand it, the last  call in a stack of apr_initalize()[N]  
>>> apr_terminate()[N] is the one  called...
>>>
>>> A simple code example:
>>>
>>>    const char *szPath = "/";
>>>    apr_initialize();
>>>    apr_pool_t *pt = svn_pool_create(NULL);
>>>    svn_fs_initialize(pt);
>>>    svn_repos_t *repo;
>>>    svn_repos_open(&repo, argv[REPO_ARG], pt);
>>>    svn_fs_t *fs = svn_repos_fs(repo);
>>>    svn_fs_root_t *root;
>>>    svn_fs_revision_root(&root, fs, 1, pt);
>>>
>>>    apr_pool_t *ptSub = svn_pool_create(pt);
>>>    apr_hash_t *hash;
>>>    svn_fs_dir_entries(&hash, root, szPath, ptSub);
>>>
>>>    svn_pool_destroy(ptSub);
>>>    svn_pool_destroy(pt);
>>>    apr_terminate();
>>>    return 0;
>>>
>>> With szPath set to "/" as above, all works as expected and the   
>>> application exits cleanly. However, if szPath were set to a path  
>>> not  available in the repo at the revision set (for example, if I  
>>> set the  path to "/foobar"), then not only does the  
>>> svn_fs_dir_entries() call  fail (yes, I know I'm not checking for  
>>> the error here, but I know it  does fail -- and I really couldn't  
>>> expect otherwise for a path not  in the repo...), but when the  
>>> time comes for the apr_terminate()  call, the application segfaults.
>>>
>>> I'm using subversion-1.6.1, compiled from source on my own  
>>> machine  with Visual Studio 2008. I'm assuming that there's some  
>>> crucial step  that I'm missing out in the code above and would  
>>> dearly appreciate  any constructive thoughts on the problem
>> You've already named the crucial step you are missing: you aren't   
>> checking for errors.
>> Subversion errors need to be checked for, and handled, if   
>> appropriate.  By not handling any returned errors, you are  
>> effectively  leaking the error memory for any error returned.  To  
>> help ensure API  users (include Subversion's own code) properly  
>> handle errors,  Subversion is configured to crash on cleanup in  
>> debug mode if an error  is left unhandled somewhere in the code.   
>> My guess is that this is  what is happening to your code.
>> If you are sure you want to ignore the returned errors, which I  
>> don't  recommend, you can wrap each function which returns an error  
>> with a  call to svn_error_clear().
>
> Hyrum,
>
> Is there a way to figure out where the unhandled error came from?   
> I'm seeing a similar core dump in our code base which is pretty  
> large (it reimplements svnserve) so figuring out where we are  
> leaking an error won't be easy.

I don't know of an easy way off hand.  I usually run into this when  
doing development, where my current delta and the number places I  
could potentially drop an error is relatively small.

It might help to look at where the code is aborting, find our which  
error is causing it to abort, and then examine that error.  The  
message and the error code may give you a hint about where it is  
coming from.  (As may the new stack tracing stuff recently introduced  
on Subversion trunk.)

Just a thought,
-Hyrum

------------------------------------------------------
http://subversion.tigris.org/ds/viewMessage.do?dsForumId=1065&dsMessageId=2356011

To unsubscribe from this discussion, e-mail: [users-unsubscribe@subversion.tigris.org].

Re: segfault at exit -- can anyone spot what I'm doing wrong?

Posted by Blair Zajac <bl...@orcaware.com>.
Hyrum K. Wright wrote:
> On May 27, 2009, at 3:24 PM, Davyd McColl wrote:
> 
>> Good day
>>
>> I have some C++ code which uses the svn_fs_* functions. I've noticed  
>> a bit of an oddity, and I'm hoping that someone can just tell me  
>> that I'm forgetting to do something. It seems that when I try to  
>> perform functions on dirs or files in the repo, if I specify a path  
>> that doesn't exist in the repo, I don't just get failure for the  
>> called function -- I also get a segfault in apr_terminate() when the  
>> last call is made to apr_terminate() (as I understand it, the last  
>> call in a stack of apr_initalize()[N] apr_terminate()[N] is the one  
>> called...
>>
>> A simple code example:
>>
>>     const char *szPath = "/";
>>     apr_initialize();
>>     apr_pool_t *pt = svn_pool_create(NULL);
>>     svn_fs_initialize(pt);
>>     svn_repos_t *repo;
>>     svn_repos_open(&repo, argv[REPO_ARG], pt);
>>     svn_fs_t *fs = svn_repos_fs(repo);
>>     svn_fs_root_t *root;
>>     svn_fs_revision_root(&root, fs, 1, pt);
>>
>>     apr_pool_t *ptSub = svn_pool_create(pt);
>>     apr_hash_t *hash;
>>     svn_fs_dir_entries(&hash, root, szPath, ptSub);
>>
>>     svn_pool_destroy(ptSub);
>>     svn_pool_destroy(pt);
>>     apr_terminate();
>>     return 0;
>>
>> With szPath set to "/" as above, all works as expected and the  
>> application exits cleanly. However, if szPath were set to a path not  
>> available in the repo at the revision set (for example, if I set the  
>> path to "/foobar"), then not only does the svn_fs_dir_entries() call  
>> fail (yes, I know I'm not checking for the error here, but I know it  
>> does fail -- and I really couldn't expect otherwise for a path not  
>> in the repo...), but when the time comes for the apr_terminate()  
>> call, the application segfaults.
>>
>> I'm using subversion-1.6.1, compiled from source on my own machine  
>> with Visual Studio 2008. I'm assuming that there's some crucial step  
>> that I'm missing out in the code above and would dearly appreciate  
>> any constructive thoughts on the problem
> 
> You've already named the crucial step you are missing: you aren't  
> checking for errors.
> 
> Subversion errors need to be checked for, and handled, if  
> appropriate.  By not handling any returned errors, you are effectively  
> leaking the error memory for any error returned.  To help ensure API  
> users (include Subversion's own code) properly handle errors,  
> Subversion is configured to crash on cleanup in debug mode if an error  
> is left unhandled somewhere in the code.  My guess is that this is  
> what is happening to your code.
> 
> If you are sure you want to ignore the returned errors, which I don't  
> recommend, you can wrap each function which returns an error with a  
> call to svn_error_clear().

Hyrum,

Is there a way to figure out where the unhandled error came from?  I'm seeing a 
similar core dump in our code base which is pretty large (it reimplements 
svnserve) so figuring out where we are leaking an error won't be easy.

Regards,
Blair

------------------------------------------------------
http://subversion.tigris.org/ds/viewMessage.do?dsForumId=1065&dsMessageId=2355991

To unsubscribe from this discussion, e-mail: [users-unsubscribe@subversion.tigris.org].

Re: segfault at exit -- can anyone spot what I'm doing wrong?

Posted by "Hyrum K. Wright" <hy...@hyrumwright.org>.
On May 27, 2009, at 11:39 PM, Davyd McColl wrote:

> On Wed, May 27, 2009 at 10:44 PM, Hyrum K. Wright <hyrum_wright@mail.utexas.edu 
> > wrote:
>
> On May 27, 2009, at 3:24 PM, Davyd McColl wrote:
>
> Good day
>
> I have some C++ code which uses the svn_fs_* functions. I've noticed  
> a bit of an oddity, and I'm hoping that someone can just tell me  
> that I'm forgetting to do something. It seems that when I try to  
> perform functions on dirs or files in the repo, if I specify a path  
> that doesn't exist in the repo, I don't just get failure for the  
> called function -- I also get a segfault in apr_terminate() when the  
> last call is made to apr_terminate() (as I understand it, the last  
> call in a stack of apr_initalize()[N] apr_terminate()[N] is the one  
> called...
>
> A simple code example:
>
>    const char *szPath = "/";
>    apr_initialize();
>    apr_pool_t *pt = svn_pool_create(NULL);
>    svn_fs_initialize(pt);
>    svn_repos_t *repo;
>    svn_repos_open(&repo, argv[REPO_ARG], pt);
>    svn_fs_t *fs = svn_repos_fs(repo);
>    svn_fs_root_t *root;
>    svn_fs_revision_root(&root, fs, 1, pt);
>
>    apr_pool_t *ptSub = svn_pool_create(pt);
>    apr_hash_t *hash;
>    svn_fs_dir_entries(&hash, root, szPath, ptSub);
>
>    svn_pool_destroy(ptSub);
>    svn_pool_destroy(pt);
>    apr_terminate();
>    return 0;
>
> With szPath set to "/" as above, all works as expected and the  
> application exits cleanly. However, if szPath were set to a path not  
> available in the repo at the revision set (for example, if I set the  
> path to "/foobar"), then not only does the svn_fs_dir_entries() call  
> fail (yes, I know I'm not checking for the error here, but I know it  
> does fail -- and I really couldn't expect otherwise for a path not  
> in the repo...), but when the time comes for the apr_terminate()  
> call, the application segfaults.
>
> I'm using subversion-1.6.1, compiled from source on my own machine  
> with Visual Studio 2008. I'm assuming that there's some crucial step  
> that I'm missing out in the code above and would dearly appreciate  
> any constructive thoughts on the problem
>
> You've already named the crucial step you are missing: you aren't  
> checking for errors.
>
> Subversion errors need to be checked for, and handled, if  
> appropriate.  By not handling any returned errors, you are  
> effectively leaking the error memory for any error returned.  To  
> help ensure API users (include Subversion's own code) properly  
> handle errors, Subversion is configured to crash on cleanup in debug  
> mode if an error is left unhandled somewhere in the code.  My guess  
> is that this is what is happening to your code.
>
> If you are sure you want to ignore the returned errors, which I  
> don't recommend, you can wrap each function which returns an error  
> with a call to svn_error_clear().
>
> -Hyrum
>
> I would have said "fair enough", but this code example above is a  
> little contrived for simplicity: in my real code, I do something  
> more along the lines of:
>
> svn_error_t *err = svn_fs_dir_entries(&hash, root, szPath, ptSub);
> if (err != SVN_NO_ERROR)
> {
>   // log the error and return from this caller level
> }
>
> In other words, I do have a kind of error handling which doesn't do  
> anything more in the logic of the program (just aborts the current  
> logic whilst logging an error), but which essentially ends up with  
> the same code path as above. Perhaps a better question then is: what  
> *should* I be doing when the dvn_fs_dir_entries()  (or other  
> svn_fs_* functions, for that matter), fail? Is there some kind of  
> invocation that I should be making to svn_* functions to handle the  
> problem? I've can't apr_hash_clear() on the hash pointer, for  
> example (expected: there was nothing to return into the hash  
> pointer). What should I be doing that I'me obviously not doing?  
> Sorry if this sounds like a desperate cry for help -- but it is.  
> Reading the subversion documentation in the headers and the  
> automatically generated documentation online hasn't shed a glaring  
> light on something that I should be doing in the event that this  
> function fails.
>
> It's critical that I find the correct "oops, something went wrong"  
> steps to follow -- this behaviour can also be replicated when trying  
> to read the contents of a file in the repo which doesn't exist. The  
> error only crops up at apr_terminate() time and obviously can't be  
> handled there. There's also a very good chance that the final  
> apr_terminate() call will be made well before the main application  
> is supposed to exit: even if I was sloppy enough not to care if my  
> app crashed at exit, I couldn't let this one slide.

The bottom line here is that the svn_error_t * should eventually be  
cleared using svn_error_clear(), whether you do that in the if  
statement above, or somewhere else is immaterial, but it needs to  
happen before you get to apr_terminate().  Are you calling that  
function on your returned errors (possibly after logging them)?

[meta comment: aborting on bad behavior like this isn't very user  
friendly, but it does keep developers honest, and helps find  
legitimate memory leaks.  Since errors are allocated in the global  
pool (because we can't depending on any other pool to last the length  
the error may be needed), they will leak if not manually cleared.   
sorry this is causing you pain, but you'll be thankful down the road.]

-Hyrum

------------------------------------------------------
http://subversion.tigris.org/ds/viewMessage.do?dsForumId=1065&dsMessageId=2356032

To unsubscribe from this discussion, e-mail: [users-unsubscribe@subversion.tigris.org].

Re: segfault at exit -- can anyone spot what I'm doing wrong?

Posted by Davyd McColl <da...@gmail.com>.
On Wed, May 27, 2009 at 10:44 PM, Hyrum K. Wright <
hyrum_wright@mail.utexas.edu> wrote:

>
> On May 27, 2009, at 3:24 PM, Davyd McColl wrote:
>
>  Good day
>>
>> I have some C++ code which uses the svn_fs_* functions. I've noticed a bit
>> of an oddity, and I'm hoping that someone can just tell me that I'm
>> forgetting to do something. It seems that when I try to perform functions on
>> dirs or files in the repo, if I specify a path that doesn't exist in the
>> repo, I don't just get failure for the called function -- I also get a
>> segfault in apr_terminate() when the last call is made to apr_terminate()
>> (as I understand it, the last call in a stack of apr_initalize()[N]
>> apr_terminate()[N] is the one called...
>>
>> A simple code example:
>>
>>    const char *szPath = "/";
>>    apr_initialize();
>>    apr_pool_t *pt = svn_pool_create(NULL);
>>    svn_fs_initialize(pt);
>>    svn_repos_t *repo;
>>    svn_repos_open(&repo, argv[REPO_ARG], pt);
>>    svn_fs_t *fs = svn_repos_fs(repo);
>>    svn_fs_root_t *root;
>>    svn_fs_revision_root(&root, fs, 1, pt);
>>
>>    apr_pool_t *ptSub = svn_pool_create(pt);
>>    apr_hash_t *hash;
>>    svn_fs_dir_entries(&hash, root, szPath, ptSub);
>>
>>    svn_pool_destroy(ptSub);
>>    svn_pool_destroy(pt);
>>    apr_terminate();
>>    return 0;
>>
>> With szPath set to "/" as above, all works as expected and the application
>> exits cleanly. However, if szPath were set to a path not available in the
>> repo at the revision set (for example, if I set the path to "/foobar"), then
>> not only does the svn_fs_dir_entries() call fail (yes, I know I'm not
>> checking for the error here, but I know it does fail -- and I really
>> couldn't expect otherwise for a path not in the repo...), but when the time
>> comes for the apr_terminate() call, the application segfaults.
>>
>> I'm using subversion-1.6.1, compiled from source on my own machine with
>> Visual Studio 2008. I'm assuming that there's some crucial step that I'm
>> missing out in the code above and would dearly appreciate any constructive
>> thoughts on the problem
>>
>
> You've already named the crucial step you are missing: you aren't checking
> for errors.
>
> Subversion errors need to be checked for, and handled, if appropriate.  By
> not handling any returned errors, you are effectively leaking the error
> memory for any error returned.  To help ensure API users (include
> Subversion's own code) properly handle errors, Subversion is configured to
> crash on cleanup in debug mode if an error is left unhandled somewhere in
> the code.  My guess is that this is what is happening to your code.
>
> If you are sure you want to ignore the returned errors, which I don't
> recommend, you can wrap each function which returns an error with a call to
> svn_error_clear().
>
> -Hyrum
>

I would have said "fair enough", but this code example above is a little
contrived for simplicity: in my real code, I do something more along the
lines of:

svn_error_t *err = svn_fs_dir_entries(&hash, root, szPath, ptSub);
if (err != SVN_NO_ERROR)
{
  // log the error and return from this caller level
}

In other words, I do have a kind of error handling which doesn't do anything
more in the logic of the program (just aborts the current logic whilst
logging an error), but which essentially ends up with the same code path as
above. Perhaps a better question then is: what *should* I be doing when the
dvn_fs_dir_entries()  (or other svn_fs_* functions, for that matter), fail?
Is there some kind of invocation that I should be making to svn_* functions
to handle the problem? I've can't apr_hash_clear() on the hash pointer, for
example (expected: there was nothing to return into the hash pointer). What
should I be doing that I'me obviously not doing? Sorry if this sounds like a
desperate cry for help -- but it is. Reading the subversion documentation in
the headers and the automatically generated documentation online hasn't shed
a glaring light on something that I should be doing in the event that this
function fails.

It's critical that I find the correct "oops, something went wrong" steps to
follow -- this behaviour can also be replicated when trying to read the
contents of a file in the repo which doesn't exist. The error only crops up
at apr_terminate() time and obviously can't be handled there. There's also a
very good chance that the final apr_terminate() call will be made well
before the main application is supposed to exit: even if I was sloppy enough
not to care if my app crashed at exit, I couldn't let this one slide.

-d

------------------------------------------------------
http://subversion.tigris.org/ds/viewMessage.do?dsForumId=1065&dsMessageId=2356028

To unsubscribe from this discussion, e-mail: [users-unsubscribe@subversion.tigris.org].

Re: segfault at exit -- can anyone spot what I'm doing wrong?

Posted by "Hyrum K. Wright" <hy...@hyrumwright.org>.
On May 27, 2009, at 3:24 PM, Davyd McColl wrote:

> Good day
>
> I have some C++ code which uses the svn_fs_* functions. I've noticed  
> a bit of an oddity, and I'm hoping that someone can just tell me  
> that I'm forgetting to do something. It seems that when I try to  
> perform functions on dirs or files in the repo, if I specify a path  
> that doesn't exist in the repo, I don't just get failure for the  
> called function -- I also get a segfault in apr_terminate() when the  
> last call is made to apr_terminate() (as I understand it, the last  
> call in a stack of apr_initalize()[N] apr_terminate()[N] is the one  
> called...
>
> A simple code example:
>
>     const char *szPath = "/";
>     apr_initialize();
>     apr_pool_t *pt = svn_pool_create(NULL);
>     svn_fs_initialize(pt);
>     svn_repos_t *repo;
>     svn_repos_open(&repo, argv[REPO_ARG], pt);
>     svn_fs_t *fs = svn_repos_fs(repo);
>     svn_fs_root_t *root;
>     svn_fs_revision_root(&root, fs, 1, pt);
>
>     apr_pool_t *ptSub = svn_pool_create(pt);
>     apr_hash_t *hash;
>     svn_fs_dir_entries(&hash, root, szPath, ptSub);
>
>     svn_pool_destroy(ptSub);
>     svn_pool_destroy(pt);
>     apr_terminate();
>     return 0;
>
> With szPath set to "/" as above, all works as expected and the  
> application exits cleanly. However, if szPath were set to a path not  
> available in the repo at the revision set (for example, if I set the  
> path to "/foobar"), then not only does the svn_fs_dir_entries() call  
> fail (yes, I know I'm not checking for the error here, but I know it  
> does fail -- and I really couldn't expect otherwise for a path not  
> in the repo...), but when the time comes for the apr_terminate()  
> call, the application segfaults.
>
> I'm using subversion-1.6.1, compiled from source on my own machine  
> with Visual Studio 2008. I'm assuming that there's some crucial step  
> that I'm missing out in the code above and would dearly appreciate  
> any constructive thoughts on the problem

You've already named the crucial step you are missing: you aren't  
checking for errors.

Subversion errors need to be checked for, and handled, if  
appropriate.  By not handling any returned errors, you are effectively  
leaking the error memory for any error returned.  To help ensure API  
users (include Subversion's own code) properly handle errors,  
Subversion is configured to crash on cleanup in debug mode if an error  
is left unhandled somewhere in the code.  My guess is that this is  
what is happening to your code.

If you are sure you want to ignore the returned errors, which I don't  
recommend, you can wrap each function which returns an error with a  
call to svn_error_clear().

-Hyrum

------------------------------------------------------
http://subversion.tigris.org/ds/viewMessage.do?dsForumId=1065&dsMessageId=2355930

To unsubscribe from this discussion, e-mail: [users-unsubscribe@subversion.tigris.org].