summaryrefslogtreecommitdiff
path: root/magic.py
diff options
context:
space:
mode:
authorAdam Hupp <adam@hupp.org>2013-06-02 15:26:18 -0700
committerAdam Hupp <adam@hupp.org>2013-06-02 15:30:29 -0700
commitfc69194b51c6f83c37f79c8834e2860213100d30 (patch)
treeef6bbb9d700b9ec907ae98e59ab99cc3f13aeda5 /magic.py
parentf85b084ac545841285848b5dbd202792187b5318 (diff)
downloadpython-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.py34
1 files changed, 16 insertions, 18 deletions
diff --git a/magic.py b/magic.py
index 9df32a1..2870a63 100644
--- a/magic.py
+++ b/magic.py
@@ -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)