From 3ebf9f14c5d41054e07c72a1f7707d0b3420b0e5 Mon Sep 17 00:00:00 2001 From: Sam Clegg Date: Sun, 19 Jun 2022 07:51:11 -0700 Subject: [PATCH] Avoid keeping module file open in tools/webassembly.py API (#17271) These was a bug in my implementation of `@cache` that I added in #17255 where it was keeping the underlying wasm file open and never actually closing it. This is because I was using the incoming arguments as the hash key instead of their hash value. The bug only manifested on windows where open files are locked in some way prevented further actions from modifying them and resulting is a strange error: ```llvm-objcopy.exe: error: permission denied``` --- .circleci/config.yml | 1 + tools/webassembly.py | 33 ++++++++++++++++----------------- 2 files changed, 17 insertions(+), 17 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 5b284af684483..ec74cb25ed86d 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -485,6 +485,7 @@ jobs: core2.test_em_asm_unicode core2.test_em_js core2.test_em_js_pthreads + other.test_c_preprocessor other.test_prejs_unicode other.test_em_js_side_module other.test_es5_transpile diff --git a/tools/webassembly.py b/tools/webassembly.py index b5c4da2c31bc0..952dccf0d3d66 100644 --- a/tools/webassembly.py +++ b/tools/webassembly.py @@ -8,6 +8,7 @@ from collections import namedtuple from enum import IntEnum +from functools import wraps import logging import os import sys @@ -54,28 +55,26 @@ def read_sleb(iobuf): return leb128.i.decode_reader(iobuf)[0] -# TODO(sbc): Use the builtin functools.cache once we update to python 3.9 -def cache(f): - results = {} +def cache(method): - def helper(*args, **kwargs): + @wraps(method) + def wrapper(self, *args, **kwargs): assert not kwargs - key = args - if key not in results: - results[key] = f(*args, **kwargs) - return results[key] + key = method + if key not in self._cache: + self._cache[key] = method(self, *args, **kwargs) + return self._cache[key] - return helper + return wrapper -def once(f): - done = False +def once(method): - def helper(*args, **kwargs): - nonlocal done - if not done: - done = True - f(*args, **kwargs) + @wraps(method) + def helper(self, *args, **kwargs): + key = method + if key not in self._cache: + self._cache[key] = method(self, *args, **kwargs) return helper @@ -167,7 +166,7 @@ def __init__(self, filename): version = self.buf.read(4) if magic != MAGIC or version != VERSION: raise InvalidWasmError(f'{filename} is not a valid wasm file') - self._done_calc_indexes = False + self._cache = {} def __del__(self): if self.buf: