Skip to content

Commit

Permalink
[Python] Ensure Python module doesn't deadlock/segv on exit, fixes #330
Browse files Browse the repository at this point in the history
  • Loading branch information
simonmichal committed Feb 28, 2019
1 parent 00b69a1 commit 912673b
Show file tree
Hide file tree
Showing 4 changed files with 91 additions and 1 deletion.
2 changes: 2 additions & 0 deletions bindings/python/libs/client/__init__.py
Expand Up @@ -4,3 +4,5 @@
from .file import File as File
from .url import URL as URL
from .copyprocess import CopyProcess as CopyProcess

import XRootD.client.finalize
35 changes: 35 additions & 0 deletions bindings/python/libs/client/finalize.py
@@ -0,0 +1,35 @@
#-------------------------------------------------------------------------------
# Copyright (c) 2012-2014 by European Organization for Nuclear Research (CERN)
# Author: Michal Simon <michal.simon@cern.ch>
#-------------------------------------------------------------------------------
# This file is part of the XRootD software suite.
#
# XRootD is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# XRootD is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with XRootD. If not, see <http://www.gnu.org/licenses/>.
#
# In applying this licence, CERN does not waive the privileges and immunities
# granted to it by virtue of its status as an Intergovernmental Organization
# or submit itself to any jurisdiction.
#------------------------------------------------------------------------------

import atexit
from pyxrootd import client

@atexit.register
def finalize():
"""Python atexit handler, will stop all XRootD client threads
(XrdCl JobManager, TaskManager and Poller) in order to ensure
no Python APIs are called after the Python Interpreter gets
finalized.
"""
client.__XrdCl_Stop_Threads()
50 changes: 50 additions & 0 deletions bindings/python/src/PyXRootDFinalize.hh
@@ -0,0 +1,50 @@
//------------------------------------------------------------------------------
// Copyright (c) 2012-2013 by European Organization for Nuclear Research (CERN)
// Author: Michal Simon <michal.simon@cern.ch>
//------------------------------------------------------------------------------
// This file is part of the XRootD software suite.
//
// XRootD is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// XRootD is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with XRootD. If not, see <http://www.gnu.org/licenses/>.
//
// In applying this licence, CERN does not waive the privileges and immunities
// granted to it by virtue of its status as an Intergovernmental Organization
// or submit itself to any jurisdiction.
//------------------------------------------------------------------------------
#ifndef BINDINGS_PYTHON_SRC_PYXROOTDFINALIZE_HH_
#define BINDINGS_PYTHON_SRC_PYXROOTDFINALIZE_HH_

#include "PyXRootD.hh"

#include "XrdCl/XrdClDefaultEnv.hh"
#include "XrdCl/XrdClPostMaster.hh"

namespace PyXRootD
{

//----------------------------------------------------------------------------
//! Waits until XrdCl JobManager, TaskManager and Poller will stop gracefully.
//!
//! To be used in Python native atexit handler in order to make sure there are
//! no outstanding threads after the Python interpreter got finalized.
//----------------------------------------------------------------------------
PyObject* __XrdCl_Stop_Threads( PyObject *self, PyObject* )
{
Py_BEGIN_ALLOW_THREADS
XrdCl::DefaultEnv::GetPostMaster()->Stop();
Py_END_ALLOW_THREADS
Py_RETURN_NONE;
}
}

#endif /* BINDINGS_PYTHON_SRC_PYXROOTDFINALIZE_HH_ */
5 changes: 4 additions & 1 deletion bindings/python/src/PyXRootDModule.cc
Expand Up @@ -27,6 +27,7 @@
#include "PyXRootDFile.hh"
#include "PyXRootDCopyProcess.hh"
#include "PyXRootDURL.hh"
#include "PyXRootDFinalize.hh"

namespace PyXRootD
{
Expand All @@ -40,7 +41,9 @@ namespace PyXRootD
//----------------------------------------------------------------------------
static PyMethodDef module_methods[] =
{
{ NULL } /* Sentinel */
// The finalization routine used in atexit handler.
{ "__XrdCl_Stop_Threads", __XrdCl_Stop_Threads, METH_NOARGS, "Stop XrdCl threads." },
{ NULL, NULL, 0, NULL }
};

#if PY_MAJOR_VERSION >= 3
Expand Down

0 comments on commit 912673b

Please sign in to comment.