Add memfd support to python based pupyimporter/memimporter

This commit is contained in:
Oleksii Shevchuk 2017-03-02 13:37:30 +02:00 committed by Oleksii Shevchuk
parent 86b1c20484
commit 6f076a6cc7
1 changed files with 37 additions and 6 deletions

View File

@ -32,13 +32,34 @@ try:
except ImportError: except ImportError:
builtin_memimporter = False builtin_memimporter = False
allow_system_packages = True allow_system_packages = True
import ctypes
import platform
import pkg_resources import pkg_resources
libc = ctypes.CDLL(None)
syscall = libc.syscall
from tempfile import mkstemp from tempfile import mkstemp
from os import chmod, unlink, close, write from os import chmod, unlink, close, write
class MemImporter(object): class MemImporter(object):
def __init__(self): def __init__(self):
self.dir = None self.dir = None
self.memfd = None
self.ready = False
if platform.system() == 'Linux':
maj, min = platform.release().split('.')[:2]
if maj >= 3 and min >= 13:
__NR_memfd_create = None
machine = platform.machine()
if machine == 'x86_64':
__NR_memfd_create = 319
elif machine == '__i386__':
__NR_memfd_create = 356
if __NR_memfd_create:
self.memfd = lambda: syscall(__NR_memfd_create, 'heap', 0x1)
self.ready = True
return
for dir in ['/dev/shm', '/tmp', '/var/tmp', '/run']: for dir in ['/dev/shm', '/tmp', '/var/tmp', '/run']:
try: try:
@ -49,6 +70,7 @@ except ImportError:
try: try:
chmod(name, 0777) chmod(name, 0777)
self.dir = dir self.dir = dir
self.ready = True
break break
finally: finally:
@ -56,7 +78,17 @@ except ImportError:
unlink(name) unlink(name)
def import_module(self, data, initfuncname, fullname, path): def import_module(self, data, initfuncname, fullname, path):
fd, name = mkstemp(dir=self.dir) fd = -1
closefd = True
if self.memfd:
fd = self.memfd()
if fd != -1:
name = '/proc/self/fd/{}'.format(fd)
closefd = False
if fd == -1:
fd, name = mkstemp(dir=self.dir)
try: try:
write(fd, data) write(fd, data)
imp.load_dynamic(fullname, name) imp.load_dynamic(fullname, name)
@ -65,13 +97,12 @@ except ImportError:
self.dir = None self.dir = None
finally: finally:
close(fd) if closefd:
unlink(name) close(fd)
unlink(name)
_memimporter = MemImporter() _memimporter = MemImporter()
if _memimporter.dir: builtin_memimporter = _memimporter.ready
print 'TMP DIR: {}'.format(_memimporter.dir)
builtin_memimporter = True
modules = {} modules = {}