fix bug in reference counting None object (#286)

This commit is contained in:
Robert Nishihara
2016-07-22 14:15:02 -07:00
committed by Philipp Moritz
parent b68512ec7d
commit baa4b7cae3
2 changed files with 24 additions and 2 deletions
+6 -2
View File
@@ -714,9 +714,13 @@ static PyObject* wait_for_next_message(PyObject* self, PyObject* args) {
Worker* worker;
PyObjectToWorker(worker_capsule, &worker);
if (std::unique_ptr<WorkerMessage> message = worker->receive_next_message()) {
// The tuple constructed below will take ownership of some None objects.
// When the tuple goes out of scope, the reference count for None will be
// decremented. Therefore, we need to increment the reference count for None
// every time we put a None in the tuple.
PyObject* t = PyTuple_New(2); // We set the items of the tuple using PyTuple_SetItem, because that transfers ownership to the tuple.
PyTuple_SetItem(t, 0, message->task.name().empty() ? Py_None : deserialize_task(worker_capsule, &message->task));
PyTuple_SetItem(t, 1, message->function.empty() ? Py_None : PyString_FromStringAndSize(message->function.data(), static_cast<ssize_t>(message->function.size())));
PyTuple_SetItem(t, 0, message->task.name().empty() ? Py_INCREF(Py_None), Py_None : deserialize_task(worker_capsule, &message->task));
PyTuple_SetItem(t, 1, message->function.empty() ? Py_INCREF(Py_None), Py_None : PyString_FromStringAndSize(message->function.data(), static_cast<ssize_t>(message->function.size())));
return t;
}
Py_RETURN_NONE;
+18
View File
@@ -4,6 +4,7 @@ import numpy as np
import time
import subprocess32 as subprocess
import os
import sys
import test_functions
import ray.array.remote as ra
@@ -489,5 +490,22 @@ class PythonModeTest(unittest.TestCase):
ray.services.cleanup()
class PythonCExtensionTest(unittest.TestCase):
def testReferenceCountNone(self):
worker_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), "test_worker.py")
ray.services.start_ray_local(num_workers=1, worker_path=worker_path)
# Make sure that we aren't accidentally messing up Python's reference counts.
for obj in [None, True, False]:
@ray.remote([], [int])
def f():
return sys.getrefcount(obj)
first_count = ray.get(f())
second_count = ray.get(f())
self.assertEqual(first_count, second_count)
ray.services.cleanup()
if __name__ == "__main__":
unittest.main()