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