[svn.haxx.se] · SVN Dev · SVN Users · SVN Org · TSVN Dev · TSVN Users · Subclipse Dev · Subclipse Users · this month's index

Re: SEGFAULTs with Python bindings and generators

From: Yasuhito FUTATSUKI <futatuki_at_yf.bsdclub.org>
Date: Wed, 30 Sep 2020 11:04:03 +0900

On 2020/09/30 10:08, Yasuhito FUTATSUKI wrote:
> On 2020/09/30 8:51, C. Michael Pilato wrote:
>> Thanks for the reply. And I see what you're trying to do there, but in
>> practice it doesn't seem to work. The swig proxy object doesn't allow
>> arbitrary attribute creation:
>>
>> AttributeError: You cannot add instance attributes to <libsvn.fs.svn_fs_t;
>>> proxy of <Swig Object of type 'svn_fs_t *' at 0x7f83bd4be420> >
>>
>
> Ah, I'm sorry you are right.
>
>> I tried to work around this using this construct:
>>
>> - fs.repos = repos
>>> + fs.__dict__['repos'] = repos
>>
>>
>> ...and that avoids the AttributeError, but alas the code still SEGFAULTs.
>> I'm attaching a(n edited for readability) log from a gdb session.
>
> I also confirmed it occured in svn_fs_fs.is_packed_rev().
>
> Perhaps SvnContentProxy object also keep fsroot object until the
> stream is closed. I found a note in docstring for svn_fs_file_contents():

It doesn't suffice. It seems fsroot is also depends on fs is living.

With following patch, I confirmed that it doesn't cause SEGV, at least
revision 200 (FreeBSD 12.1, Python 3.7.8).
[[[
--- pysvnget.orig 2020-09-29 22:00:40.000000000 +0900
+++ pysvnget 2020-09-30 11:02:19.300420000 +0900
@@ -11,6 +11,7 @@ import svn.core, svn.repos, svn.fs
 class SvnContentProxy:
   def __init__(self, fsroot, path):
       self.stream = svn.fs.file_contents(fsroot, path)
+ self.root = fsroot
 
   def get_generator(self):
       while 1:
@@ -20,11 +21,15 @@ class SvnContentProxy:
               break
           yield chunk
       svn.core.svn_stream_close(self.stream)
+ svn.root = None
 
 def get_generator(repos_path, peg_revision, path):
- fs = svn.repos.fs(svn.repos.open(repos_path))
+ repos = svn.repos.open(repos_path)
+ fs = svn.repos.fs(repos)
+ fs.__dict__['repos'] = repos
     peg_revision = peg_revision or svn.fs.youngest_rev(fs)
     fsroot = svn.fs.revision_root(fs, peg_revision)
+ fsroot.__dict__['fs'] = fs
     return SvnContentProxy(fsroot, path).get_generator()
 #
 # --------------------------------------------------------------------------
]]]

>
> """
> * @todo kff: I am worried about lifetime issues with this pool vs
> * the trail created farther down the call stack. Trace this function
> * to investigate...
>
> """
>
> I worry about the svn_stream_t * object returned by svn_fs_file_contents()
> depends that svn_fs_root_t * root is living.
>
> Cheers,
>

Cheers,

-- 
Yasuhito FUTATSUKI <futatuki_at_yf.bsclub.org>
Received on 2020-09-30 04:07:15 CEST

This is an archived mail posted to the Subversion Dev mailing list.

This site is subject to the Apache Privacy Policy and the Apache Public Forum Archive Policy.