mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
Make lopen() atomic on linux (if the kernel supports O_CLOEXEC)
This commit is contained in:
parent
a5e071d091
commit
bee4b2b9c7
@ -16,7 +16,7 @@ __builtin__.__dict__['_'] = lambda s: s
|
|||||||
# immediately translated to the environment language
|
# immediately translated to the environment language
|
||||||
__builtin__.__dict__['__'] = lambda s: s
|
__builtin__.__dict__['__'] = lambda s: s
|
||||||
|
|
||||||
from calibre.constants import iswindows, preferred_encoding, plugins, isosx
|
from calibre.constants import iswindows, preferred_encoding, plugins, isosx, islinux
|
||||||
|
|
||||||
_run_once = False
|
_run_once = False
|
||||||
winutil = winutilerror = None
|
winutil = winutilerror = None
|
||||||
@ -24,7 +24,7 @@ winutil = winutilerror = None
|
|||||||
if not _run_once:
|
if not _run_once:
|
||||||
_run_once = True
|
_run_once = True
|
||||||
|
|
||||||
################################################################################
|
#
|
||||||
# Platform specific modules
|
# Platform specific modules
|
||||||
if iswindows:
|
if iswindows:
|
||||||
winutil, winutilerror = plugins['winutil']
|
winutil, winutilerror = plugins['winutil']
|
||||||
@ -33,12 +33,12 @@ if not _run_once:
|
|||||||
if len(sys.argv) > 1 and not isinstance(sys.argv[1], unicode):
|
if len(sys.argv) > 1 and not isinstance(sys.argv[1], unicode):
|
||||||
sys.argv[1:] = winutil.argv()[1-len(sys.argv):]
|
sys.argv[1:] = winutil.argv()[1-len(sys.argv):]
|
||||||
|
|
||||||
################################################################################
|
#
|
||||||
# Ensure that all temp files/dirs are created under a calibre tmp dir
|
# Ensure that all temp files/dirs are created under a calibre tmp dir
|
||||||
from calibre.ptempfile import base_dir
|
from calibre.ptempfile import base_dir
|
||||||
base_dir()
|
base_dir()
|
||||||
|
|
||||||
################################################################################
|
#
|
||||||
# Convert command line arguments to unicode
|
# Convert command line arguments to unicode
|
||||||
enc = preferred_encoding
|
enc = preferred_encoding
|
||||||
if isosx:
|
if isosx:
|
||||||
@ -52,19 +52,18 @@ if not _run_once:
|
|||||||
if not isinstance(sys.argv[i], unicode):
|
if not isinstance(sys.argv[i], unicode):
|
||||||
sys.argv[i] = sys.argv[i].decode(enc, 'replace')
|
sys.argv[i] = sys.argv[i].decode(enc, 'replace')
|
||||||
|
|
||||||
################################################################################
|
#
|
||||||
# Setup resources
|
# Setup resources
|
||||||
import calibre.utils.resources as resources
|
import calibre.utils.resources as resources
|
||||||
resources
|
resources
|
||||||
|
|
||||||
|
#
|
||||||
################################################################################
|
|
||||||
# Setup translations
|
# Setup translations
|
||||||
from calibre.utils.localization import set_translators
|
from calibre.utils.localization import set_translators
|
||||||
|
|
||||||
set_translators()
|
set_translators()
|
||||||
|
|
||||||
################################################################################
|
#
|
||||||
# Initialize locale
|
# Initialize locale
|
||||||
# Import string as we do not want locale specific
|
# Import string as we do not want locale specific
|
||||||
# string.whitespace/printable, on windows especially, this causes problems.
|
# string.whitespace/printable, on windows especially, this causes problems.
|
||||||
@ -82,7 +81,7 @@ if not _run_once:
|
|||||||
except:
|
except:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
################################################################################
|
#
|
||||||
|
|
||||||
def local_open(name, mode='r', bufsize=-1):
|
def local_open(name, mode='r', bufsize=-1):
|
||||||
'''
|
'''
|
||||||
@ -93,6 +92,7 @@ if not _run_once:
|
|||||||
'''
|
'''
|
||||||
if iswindows:
|
if iswindows:
|
||||||
class fwrapper(object):
|
class fwrapper(object):
|
||||||
|
|
||||||
def __init__(self, name, fobject):
|
def __init__(self, name, fobject):
|
||||||
object.__setattr__(self, 'fobject', fobject)
|
object.__setattr__(self, 'fobject', fobject)
|
||||||
object.__setattr__(self, 'name', name)
|
object.__setattr__(self, 'name', name)
|
||||||
@ -129,7 +129,6 @@ if not _run_once:
|
|||||||
fobject = object.__getattribute__(self, 'fobject')
|
fobject = object.__getattribute__(self, 'fobject')
|
||||||
return fobject.__exit__(*args)
|
return fobject.__exit__(*args)
|
||||||
|
|
||||||
|
|
||||||
m = mode[0]
|
m = mode[0]
|
||||||
random = len(mode) > 1 and mode[1] == '+'
|
random = len(mode) > 1 and mode[1] == '+'
|
||||||
binary = mode[-1] == 'b'
|
binary = mode[-1] == 'b'
|
||||||
@ -162,8 +161,15 @@ if not _run_once:
|
|||||||
cloexec_flag = fcntl.FD_CLOEXEC
|
cloexec_flag = fcntl.FD_CLOEXEC
|
||||||
except AttributeError:
|
except AttributeError:
|
||||||
cloexec_flag = 1
|
cloexec_flag = 1
|
||||||
|
# Python 2.x uses fopen which on recent glibc/linux kernel at least
|
||||||
|
# respects the 'e' mode flag. On OS X the e is ignored. So to try
|
||||||
|
# to get atomicity where possible we pass 'e' and then only use
|
||||||
|
# fcntl only if CLOEXEC was not set.
|
||||||
|
if islinux:
|
||||||
|
mode += 'e'
|
||||||
ans = open(name, mode, bufsize)
|
ans = open(name, mode, bufsize)
|
||||||
old = fcntl.fcntl(ans, fcntl.F_GETFD)
|
old = fcntl.fcntl(ans, fcntl.F_GETFD)
|
||||||
|
if not (old & cloexec_flag):
|
||||||
fcntl.fcntl(ans, fcntl.F_SETFD, old | cloexec_flag)
|
fcntl.fcntl(ans, fcntl.F_SETFD, old | cloexec_flag)
|
||||||
return ans
|
return ans
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user