def __init__(self, name=None, create=False, size=0):
        if not size >= 0:
            raise ValueError("'size' must be a positive integer")
        if create:
            self._flags = _O_CREX | os.O_RDWR
            if size == 0:
                raise ValueError(
                    "'size' must be a positive number different from zero")
        if name is None and not self._flags & os.O_EXCL:
            raise ValueError("'name' can only be None if create=True")

        if _USE_POSIX:

            # POSIX Shared Memory

            if name is None:
                while True:
                    name = _make_filename()
                    try:
                        self._fd = _posixshmem.shm_open(name,
                                                        self._flags,
                                                        mode=self._mode)

                    except FileExistsError:
                        continue
                    self._name = name
                    break
            else:
                name = "/" + name if self._prepend_leading_slash else name
                self._fd = _posixshmem.shm_open(name,
                                                self._flags,
                                                mode=self._mode)

                self._name = name
            try:
                if create and size:
                    os.ftruncate(self._fd, size)
                stats = os.fstat(self._fd)
                size = stats.st_size
                self._mmap = mmap.mmap(self._fd, size)
            except OSError:
                self.unlink()
                raise
            from multiprocessing.resource_tracker import register
            register(self._name, "shared_memory")
        else:

            # Windows Named Shared Memory

            if create:
                while True:
                    temp_name = _make_filename() if name is None else name
                    # Create and reserve shared memory block with this name
                    # until it can be attached to by mmap.
                    h_map = _winapi.CreateFileMapping(
                        _winapi.INVALID_HANDLE_VALUE, _winapi.NULL,
                        _winapi.PAGE_READWRITE, (size >> 32) & 0xFFFFFFFF,
                        size & 0xFFFFFFFF, temp_name)
                    try:
                        last_error_code = _winapi.GetLastError()
                        if last_error_code == _winapi.ERROR_ALREADY_EXISTS:
                            if name is not None:
                                raise FileExistsError(
                                    errno.EEXIST, os.strerror(errno.EEXIST),
                                    name, _winapi.ERROR_ALREADY_EXISTS)
                            else:
                                continue
                        self._mmap = mmap.mmap(-1, size, tagname=temp_name)
                    finally:
                        _winapi.CloseHandle(h_map)
                    self._name = temp_name
                    break

            else:
                self._name = name
                # Dynamically determine the existing named shared memory
                # block's size which is likely a multiple of mmap.PAGESIZE.
                h_map = _winapi.OpenFileMapping(_winapi.FILE_MAP_READ, False,
                                                name)
                try:
                    p_buf = _winapi.MapViewOfFile(h_map, _winapi.FILE_MAP_READ,
                                                  0, 0, 0)
                finally:
                    _winapi.CloseHandle(h_map)
                size = _winapi.VirtualQuerySize(p_buf)
                self._mmap = mmap.mmap(-1, size, tagname=name)

        self._size = size
        self._buf = memoryview(self._mmap)
Beispiel #2
0
    def __init__(self,
                 name: str = '',
                 size: int = 0,
                 readonly: bool = False,
                 mode: int = stat.S_IREAD | stat.S_IWRITE,
                 prefix: str = 'calibre-'):
        if size < 0:
            raise TypeError("'size' must be a non-negative integer")
        if size and name:
            raise TypeError('Cannot specify both name and size')
        if not name:
            flags = os.O_CREAT | os.O_EXCL
            if not size:
                raise TypeError("'size' must be > 0")
        else:
            flags = 0
        flags |= os.O_RDONLY if readonly else os.O_RDWR
        access = mmap.ACCESS_READ if readonly else mmap.ACCESS_WRITE

        create = not name
        tries = 30
        while not name and tries > 0:
            tries -= 1
            q = make_filename(prefix)
            if iswindows:
                h_map = _winapi.CreateFileMapping(
                    _winapi.INVALID_HANDLE_VALUE, _winapi.NULL,
                    _winapi.PAGE_READONLY
                    if readonly else _winapi.PAGE_READWRITE,
                    (size >> 32) & 0xFFFFFFFF, size & 0xFFFFFFFF, q)
                try:
                    last_error_code = _winapi.GetLastError()
                    if last_error_code == _winapi.ERROR_ALREADY_EXISTS:
                        continue
                    self._mmap = mmap.mmap(-1, size, tagname=q, access=access)
                    name = q
                finally:
                    _winapi.CloseHandle(h_map)
            else:
                try:
                    self._fd = _posixshmem.shm_open(q, flags, mode=mode)
                    name = q
                except FileExistsError:
                    continue
        if tries <= 0:
            raise OSError(
                f'Failed to create a uniquely named SHM file, try shortening the prefix from: {prefix}'
            )
        self._name = name

        if not create and iswindows:
            h_map = _winapi.OpenFileMapping(_winapi.FILE_MAP_READ, False, name)
            try:
                p_buf = _winapi.MapViewOfFile(h_map, _winapi.FILE_MAP_READ, 0,
                                              0, 0)
            finally:
                _winapi.CloseHandle(h_map)
            size = _winapi.VirtualQuerySize(p_buf)
            self._mmap = mmap.mmap(-1, size, tagname=name)
        if not iswindows:
            if not create:
                self._fd = _posixshmem.shm_open(name, flags, mode)
            try:
                if flags & os.O_CREAT and size:
                    os.ftruncate(self._fd, size)
                self.stats = os.fstat(self._fd)
                size = self.stats.st_size
                self._mmap = mmap.mmap(self._fd, size, access=access)
            except OSError:
                self.unlink()
                raise

        self._size = size