1 /************************************************************************* 2 * 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * Copyright 2000, 2010 Oracle and/or its affiliates. 6 * 7 * OpenOffice.org - a multi-platform office productivity suite 8 * 9 * This file is part of OpenOffice.org. 10 * 11 * OpenOffice.org is free software: you can redistribute it and/or modify 12 * it under the terms of the GNU Lesser General Public License version 3 13 * only, as published by the Free Software Foundation. 14 * 15 * OpenOffice.org is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU Lesser General Public License version 3 for more details 19 * (a copy is included in the LICENSE file that accompanied this code). 20 * 21 * You should have received a copy of the GNU Lesser General Public License 22 * version 3 along with OpenOffice.org. If not, see 23 * <http://www.openoffice.org/license.html> 24 * for a copy of the LGPLv3 License. 25 * 26 ************************************************************************/ 27 #include <pyuno_impl.hxx> 28 #include <osl/thread.hxx> 29 namespace pyuno 30 { 31 32 bool g_destructorsOfStaticObjectsHaveBeenCalled; 33 class StaticDestructorGuard 34 { 35 public: 36 ~StaticDestructorGuard() 37 { 38 g_destructorsOfStaticObjectsHaveBeenCalled = true; 39 } 40 }; 41 StaticDestructorGuard guard; 42 43 static bool isAfterUnloadOrPy_Finalize() 44 { 45 return g_destructorsOfStaticObjectsHaveBeenCalled || 46 !Py_IsInitialized(); 47 } 48 49 class GCThread : public ::osl::Thread 50 { 51 PyObject *mPyObject; 52 PyInterpreterState *mPyInterpreter; 53 GCThread( const GCThread & ); // not implemented 54 GCThread &operator =( const GCThread & ); // not implemented 55 56 public: 57 GCThread( PyInterpreterState *interpreter, PyObject * object ); 58 virtual void SAL_CALL run(); 59 virtual void SAL_CALL onTerminated(); 60 }; 61 62 63 GCThread::GCThread( PyInterpreterState *interpreter, PyObject * object ) : 64 mPyObject( object ), mPyInterpreter( interpreter ) 65 {} 66 67 void GCThread::run() 68 { 69 // otherwise we crash here, when main has been left already 70 if( isAfterUnloadOrPy_Finalize() ) 71 return; 72 try 73 { 74 PyThreadAttach g( (PyInterpreterState*)mPyInterpreter ); 75 { 76 Runtime runtime; 77 78 // remove the reference from the pythonobject2adapter map 79 PyRef2Adapter::iterator ii = 80 runtime.getImpl()->cargo->mappedObjects.find( mPyObject ); 81 if( ii != runtime.getImpl()->cargo->mappedObjects.end() ) 82 { 83 runtime.getImpl()->cargo->mappedObjects.erase( ii ); 84 } 85 86 Py_XDECREF( mPyObject ); 87 } 88 } 89 catch( com::sun::star::uno::RuntimeException & e ) 90 { 91 rtl::OString msg; 92 msg = rtl::OUStringToOString( e.Message, RTL_TEXTENCODING_ASCII_US ); 93 fprintf( stderr, "Leaking python objects bridged to UNO for reason %s\n",msg.getStr()); 94 } 95 } 96 97 98 void GCThread::onTerminated() 99 { 100 delete this; 101 } 102 103 void decreaseRefCount( PyInterpreterState *interpreter, PyObject *object ) 104 { 105 // otherwise we crash in the last after main ... 106 if( isAfterUnloadOrPy_Finalize() ) 107 return; 108 109 // delegate to a new thread, because there does not seem 110 // to be a method, which tells, whether the global 111 // interpreter lock is held or not 112 // TODO: Look for a more efficient solution 113 osl::Thread *t = new GCThread( interpreter, object ); 114 t->create(); 115 } 116 117 } 118