• K
    Git::SVN::*: avoid premature FileHandle closure · e426311b
    Kyle J. McKay 提交于
    Since b19138b (git-svn: Make it incrementally faster by minimizing temp
    files, v1.6.0), git-svn has been using the Git.pm temp_acquire and
    temp_release mechanism to avoid unnecessary temp file churn and provide
    a speed boost.
    
    However, that change introduced a call to temp_acquire inside the
    Git::SVN::Fetcher::close_file function for an 'svn_hash' temp file.
    Because an SVN::Pool is active at the time this function is called, if
    the Git::temp_acquire function ends up actually creating a new
    FileHandle for the temp file (which it will the first time it's called
    with the name 'svn_hash') that FileHandle will end up in the SVN::Pool
    and should that pool have SVN::Pool::clear called on it that FileHandle
    will be closed out from under Git::temp_acquire.
    
    Since the only call site to Git::temp_acquire with the name 'svn_hash'
    is inside the close_file function, if an 'svn_hash' temp file is ever
    created its FileHandle is guaranteed to be created in the active
    SVN::Pool.
    
    This has not been a problem in the past because the SVN::Pool was not
    being cleared.  However, since dfa72fdb (git-svn: reload RA every
    log-window-size, v2.2.0) the pool has been getting cleared periodically
    at which point the FileHandle for the 'svn_hash' temp file gets closed.
    Any subsequent calls to Git::temp_acquire for 'svn_hash', however,
    succeed without creating/opening a new temporary file since it still has
    the now invalid FileHandle in its cache.  Callers that then attempt to
    use that FileHandle fail with an error.
    
    We avoid this problem by making sure the 'svn_hash' temp file is created
    in the same place the 'svn_delta_...' and 'git_blob_...' temp files are
    (and then temp_release'd) so that it can be safely used inside the
    close_file function without having its FileHandle end up in an SVN::Pool
    that gets cleared.
    
    Additionally the Git.pm cat_blob function creates a bidirectional pipe
    FileHandle using the IPC::Open2::open2 function.  If that handle is
    created too late, it also gets caught up in the SVN::Pool and incorrectly
    closed by the SVN::Pool::clear call.  But this only seems to happen with
    more recent versions of Perl and svn.
    
    To avoid this problem we add an explicit call to _open_cat_blob_if_needed
    before the first call to SVN::Pool->new_default to make sure the open2
    handle does not end up in the SVN::Pool.
    Signed-off-by: NKyle J. McKay <mackyle@gmail.com>
    Signed-off-by: NEric Wong <normalperson@yhbt.net>
    Signed-off-by: NJunio C Hamano <gitster@pobox.com>
    e426311b
Fetcher.pm 18.1 KB