xref: /aoo41x/main/pyuno/source/module/pyuno_gc.cxx (revision 67c7d1c1)
1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 #include <pyuno_impl.hxx>
24 #include <osl/thread.hxx>
25 namespace pyuno
26 {
27 
28 bool g_destructorsOfStaticObjectsHaveBeenCalled;
29 class StaticDestructorGuard
30 {
31 public:
~StaticDestructorGuard()32     ~StaticDestructorGuard()
33     {
34         g_destructorsOfStaticObjectsHaveBeenCalled = true;
35     }
36 };
37 StaticDestructorGuard guard;
38 
isAfterUnloadOrPy_Finalize()39 static bool isAfterUnloadOrPy_Finalize()
40 {
41     return g_destructorsOfStaticObjectsHaveBeenCalled ||
42         !Py_IsInitialized();
43 }
44 
45 class GCThread : public ::osl::Thread
46 {
47     PyObject *mPyObject;
48     PyInterpreterState *mPyInterpreter;
49     GCThread( const GCThread & ); // not implemented
50     GCThread &operator =( const GCThread & ); // not implemented
51 
52 public:
53     GCThread( PyInterpreterState *interpreter, PyObject * object );
54     virtual void SAL_CALL run();
55     virtual void SAL_CALL onTerminated();
56 };
57 
58 
GCThread(PyInterpreterState * interpreter,PyObject * object)59 GCThread::GCThread( PyInterpreterState *interpreter, PyObject * object ) :
60     mPyObject( object ), mPyInterpreter( interpreter )
61 {}
62 
run()63 void GCThread::run()
64 {
65     //  otherwise we crash here, when main has been left already
66     if( isAfterUnloadOrPy_Finalize() )
67         return;
68     try
69     {
70         PyThreadAttach g( (PyInterpreterState*)mPyInterpreter );
71         {
72             Runtime runtime;
73 
74             // remove the reference from the pythonobject2adapter map
75             PyRef2Adapter::iterator ii =
76                 runtime.getImpl()->cargo->mappedObjects.find( mPyObject );
77             if( ii != runtime.getImpl()->cargo->mappedObjects.end() )
78             {
79                 runtime.getImpl()->cargo->mappedObjects.erase( ii );
80             }
81 
82             Py_XDECREF( mPyObject );
83         }
84     }
85     catch( com::sun::star::uno::RuntimeException & e )
86     {
87         rtl::OString msg;
88         msg = rtl::OUStringToOString( e.Message, RTL_TEXTENCODING_ASCII_US );
89         fprintf( stderr, "Leaking python objects bridged to UNO for reason %s\n",msg.getStr());
90     }
91 }
92 
93 
onTerminated()94 void GCThread::onTerminated()
95 {
96     delete this;
97 }
98 
decreaseRefCount(PyInterpreterState * interpreter,PyObject * object)99 void decreaseRefCount( PyInterpreterState *interpreter, PyObject *object )
100 {
101     //  otherwise we crash in the last after main ...
102     if( isAfterUnloadOrPy_Finalize() )
103         return;
104 
105     // delegate to a new thread, because there does not seem
106     // to be a method, which tells, whether the global
107     // interpreter lock is held or not
108     // TODO: Look for a more efficient solution
109     osl::Thread *t = new GCThread( interpreter, object );
110     t->create();
111 }
112 
113 }
114