diff options
| author | Adam Hupp <adam@hupp.org> | 2013-06-02 15:26:18 -0700 |
|---|---|---|
| committer | Adam Hupp <adam@hupp.org> | 2013-06-02 15:30:29 -0700 |
| commit | fc69194b51c6f83c37f79c8834e2860213100d30 (patch) | |
| tree | ef6bbb9d700b9ec907ae98e59ab99cc3f13aeda5 /magic.py | |
| parent | f85b084ac545841285848b5dbd202792187b5318 (diff) | |
| download | python-magic-fc69194b51c6f83c37f79c8834e2860213100d30.tar.gz | |
- avoid segfault when used in multiple threads via magic.from_buffer/from_file methods
- add hard check to prevent this in the future (possibly breaking change)
Diffstat (limited to 'magic.py')
| -rw-r--r-- | magic.py | 34 |
1 files changed, 16 insertions, 18 deletions
@@ -21,6 +21,7 @@ import sys import os.path import ctypes import ctypes.util +import threading from ctypes import c_char_p, c_int, c_size_t, c_void_p @@ -51,11 +52,13 @@ class Magic: magic_load(self.cookie, magic_file) + self.thread = threading.current_thread() def from_buffer(self, buf): """ Identify the contents of `buf` """ + self._thread_check() return magic_buffer(self.cookie, buf) def from_file(self, filename): @@ -63,38 +66,33 @@ class Magic: Identify the contents of file `filename` raises IOError if the file does not exist """ - + self._thread_check() if not os.path.exists(filename): raise IOError("File does not exist: " + filename) return magic_file(self.cookie, filename) + def _thread_check(self): + if self.thread != threading.current_thread(): + raise Exception('attempting to use libmagic on multiple threads will ' + 'end in SEGV. Prefer to use the module functions ' + 'from_file or from_buffer, or carefully manage direct ' + 'use of the Magic class') + def __del__(self): # during shutdown magic_close may have been cleared already if self.cookie and magic_close: magic_close(self.cookie) self.cookie = None -_magic_mime = None -_magic = None -def _get_magic_mime(): - global _magic_mime - if not _magic_mime: - _magic_mime = Magic(mime=True) - return _magic_mime - -def _get_magic(): - global _magic - if not _magic: - _magic = Magic() - return _magic +instances = threading.local() def _get_magic_type(mime): - if mime: - return _get_magic_mime() - else: - return _get_magic() + i = instances.__dict__.get(mime) + if i is None: + i = instances.__dict__[mime] = Magic(mime=mime) + return i def from_file(filename, mime=False): m = _get_magic_type(mime) |
