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: 32 ~StaticDestructorGuard() 33 { 34 g_destructorsOfStaticObjectsHaveBeenCalled = true; 35 } 36 }; 37 StaticDestructorGuard guard; 38 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 59 GCThread::GCThread( PyInterpreterState *interpreter, PyObject * object ) : 60 mPyObject( object ), mPyInterpreter( interpreter ) 61 {} 62 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 94 void GCThread::onTerminated() 95 { 96 delete this; 97 } 98 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