python: Mac OS X. ошибка malloc. освобожденный указатель не был выделен. прерывание ловушки 6
Я использую многопоточный скрипт на Python. он будет сканировать сеть и вставлять / обновлять в mysql. вот мой код
mythread.py
import threading
import time
class MyThread (threading.Thread):
def __init__(self, threadID, threadname, q):
threading.Thread.__init__(self)
self.threadID = threadID
self.threadname = threadname
self.queue = q
self.__exitFlag = False
self.__signal_lock = threading.Lock()
def run(self):
print "Starting " + self.threadname
self.process_data()
print "Exiting " + self.threadname
def stop(self):
with self.__signal_lock:
self.__exitFlag = True
def process_data(self):
while not self.__exitFlag:
if not self.queue.empty():
data = self.queue.get()
# crawl data from the web...
# update to mysql
# assuming we have already connected mysql:
# db = MySQLDb()
# db.connect
query = ""
db.query(query)
mysql_db.py
class MySQLDb:
conn = None
def connect(self):
self.conn = MySQLdb.connect(
host="127.0.0.1",
user = "root",
passwd = "password",
db = "moviestats")
self.cursor = self.conn.cursor(MySQLdb.cursors.DictCursor)
def query(self, sql):
try:
self.cursor.execute(sql)
self.conn.commit()
except (AttributeError, MySQLdb.OperationalError):
# solution to: MySQL server has gone away
self.cursor.close()
self.connect()
self.cursor = self.conn.cursor(MySQLdb.cursors.DictCursor)
self.cursor.execute(sql)
self.conn.commit()
Вот журнал ошибок:
Process: Python [905]
Path: /Library/Frameworks/Python.framework/Versions/2.7/Resources/Python.app/Contents/MacOS/Python
Identifier: Python
Version: 2.7.7 (2.7.7)
Code Type: X86-64 (Native)
Parent Process: bash [751]
Responsible: Terminal [410]
User ID: 501
Date/Time: 2014-07-09 22:31:43.221 +0800
OS Version: Mac OS X 10.9.3 (13D65)
Report Version: 11
....
....
Crashed Thread: 5
Exception Type: EXC_CRASH (SIGABRT)
Exception Codes: 0x0000000000000000, 0x0000000000000000
Application Specific Information:
abort() called
*** error for object 0x100a4b600: pointer being freed was not allocated
......
Thread 5 Crashed:
0 libsystem_kernel.dylib 0x00007fff83153866 __pthread_kill + 10
1 libsystem_pthread.dylib 0x00007fff8de8735c pthread_kill + 92
2 libsystem_c.dylib 0x00007fff8ef88b1a abort + 125
3 libsystem_malloc.dylib 0x00007fff8220707f free + 411
4 libmysqlclient.18.dylib 0x0000000101027302 vio_delete + 44
5 libmysqlclient.18.dylib 0x000000010100709a end_server + 48
6 libmysqlclient.18.dylib 0x0000000101006f81 cli_safe_read + 49
7 libmysqlclient.18.dylib 0x000000010100b469 cli_read_query_result + 26
8 libmysqlclient.18.dylib 0x000000010100a648 mysql_real_query + 83
9 _mysql.so 0x0000000100533be8 _mysql_ConnectionObject_query + 85
10 org.python.python 0x00000001000c2fad PyEval_EvalFrameEx + 21405
11 org.python.python 0x00000001000c3bfa PyEval_EvalFrameEx + 24554
12 org.python.python 0x00000001000c3bfa PyEval_EvalFrameEx + 24554
13 org.python.python 0x00000001000c4fb3 PyEval_EvalCodeEx + 2115
14 org.python.python 0x00000001000c33f0 PyEval_EvalFrameEx + 22496
15 org.python.python 0x00000001000c3bfa PyEval_EvalFrameEx + 24554
16 org.python.python 0x00000001000c3bfa PyEval_EvalFrameEx + 24554
17 org.python.python 0x00000001000c4fb3 PyEval_EvalCodeEx + 2115
18 org.python.python 0x00000001000c33f0 PyEval_EvalFrameEx + 22496
19 org.python.python 0x00000001000c3bfa PyEval_EvalFrameEx + 24554
20 org.python.python 0x00000001000c3bfa PyEval_EvalFrameEx + 24554
21 org.python.python 0x00000001000c3bfa PyEval_EvalFrameEx + 24554
22 org.python.python 0x00000001000c4fb3 PyEval_EvalCodeEx + 2115
23 org.python.python 0x000000010003eac0 function_call + 176
24 org.python.python 0x000000010000ceb2 PyObject_Call + 98
25 org.python.python 0x000000010001f56d instancemethod_call + 365
26 org.python.python 0x000000010000ceb2 PyObject_Call + 98
27 org.python.python 0x00000001000bc957 PyEval_CallObjectWithKeywords + 87
28 org.python.python 0x0000000100102f27 t_bootstrap + 71
29 libsystem_pthread.dylib 0x00007fff8de86899 _pthread_body + 138
30 libsystem_pthread.dylib 0x00007fff8de8672a _pthread_start + 137
31 libsystem_pthread.dylib 0x00007fff8de8afc9 thread_start + 13
Я запустил скрипт с 50 потоками. Ошибка происходит с перебоями, но она повторяется. Я сузил проблему, и это из-за вставки / обновления MySQL. Я читал, что это может быть связано с проблемой параллелизма, но как мне это исправить?
3 ответа
Я столкнулся с той же ошибкой malloc на OSX, используя MySQLdb. Моей ошибкой было то, что я разделял соединения MySQLdb между потоками. Использование соединения в потоке исправило это для меня.
Из документации http://mysql-python.sourceforge.net/MySQLdb.html:
Протокол MySQL не может обрабатывать несколько потоков, используя одно и то же соединение одновременно. В некоторых более ранних версиях MySQLdb блокировка использовалась для обеспечения безопасности потока 2. Хотя это не очень сложно реализовать с помощью стандартного класса Cursor (который использует mysql_store_result()), он усложняется SSCursor (который использует mysql_use_result(); с последним Вы должны убедиться, что все строки были прочитаны, прежде чем можно будет выполнить другой запрос. Это дополнительно усложняется добавлением транзакций, поскольку транзакции начинаются, когда курсор выполняет запрос, но заканчиваются, когда COMMIT или ROLLBACK выполняются объектом Connection. потоки просто не могут совместно использовать соединение во время выполнения транзакции, в дополнение к невозможности поделиться им во время выполнения запроса, что чрезмерно усложняет код до такой степени, что оно просто не стоит.
Общий итог этого: не делиться соединениями между потоками. Это действительно не стоит ваших или моих усилий, и в конечном итоге, вероятно, ухудшит производительность, поскольку сервер MySQL запускает отдельный поток для каждого соединения. Вы, конечно, можете делать такие вещи, как соединения с кешем в пуле, и передавать эти соединения одному потоку за раз. Если вы позволите двум потокам использовать соединение одновременно, клиентская библиотека MySQL, вероятно, выскочит и умрет. Вы были предупреждены.
У меня была та же проблема, но я думал о способах не многопоточного доступа к базе данных. И после дальнейших размышлений я считаю плохой практикой иметь множество потоков со связями (или, по крайней мере, это может быть сложным делом). Подумайте о том, как выполнять массовое чтение и запись, а также выполнять многопоточность обработки без участия базы данных.
Это может все еще быть ошибкой в привязке Python, но я смог добиться прогресса, упростив способ, которым программа обращалась к базе данных, и распараллеливая код, где это действительно нужно было распараллелить. Надеюсь это поможет!
В целом эта ошибка может быть стохастической. Я столкнулся с этой ошибкой, но после запуска программы снова не получил ошибку. Я запускал свою программу (которая не связана с mysql_db, хотя и сложна) 5 раз. Я нашел эту ошибку только на первом и четвертом прогоне.