summaryrefslogtreecommitdiff
path: root/psprint
diff options
context:
space:
mode:
authorJens-Heiner Rechtien <hr@openoffice.org>2005-06-06 15:07:42 +0000
committerJens-Heiner Rechtien <hr@openoffice.org>2005-06-06 15:07:42 +0000
commitccdfa219503a62f22365055b479dd8fe06e200ee (patch)
tree54879044840668a85546b354d58042065ab74d35 /psprint
parent6bdaeae06507d1d47dc4a33be5ba67f3f991ba65 (diff)
INTEGRATION: CWS gslpatches (1.11.6); FILE MERGED
2005/04/22 08:19:23 pl 1.11.6.1: #i45318# cups threading issue
Diffstat (limited to 'psprint')
-rw-r--r--psprint/source/printer/cupsmgr.cxx167
1 files changed, 109 insertions, 58 deletions
diff --git a/psprint/source/printer/cupsmgr.cxx b/psprint/source/printer/cupsmgr.cxx
index 7fa6892fca2b..cd16c3c58fb9 100644
--- a/psprint/source/printer/cupsmgr.cxx
+++ b/psprint/source/printer/cupsmgr.cxx
@@ -2,9 +2,9 @@
*
* $RCSfile: cupsmgr.cxx,v $
*
- * $Revision: 1.11 $
+ * $Revision: 1.12 $
*
- * last change: $Author: rt $ $Date: 2005-03-30 08:53:00 $
+ * last change: $Author: hr $ $Date: 2005-06-06 16:07:42 $
*
* The Contents of this file are made available subject to the terms of
* either of the following licenses
@@ -84,6 +84,7 @@ class CUPSWrapper
{
oslModule m_pLib;
osl::Mutex m_aGetPPDMutex;
+ bool m_bPPDThreadRunning;
int (*m_pcupsPrintFile)(const char*, const char*, const char*, int, cups_option_t*);
int (*m_pcupsGetDests)(cups_dest_t**);
@@ -123,7 +124,7 @@ public:
cups_option_t* pOptions )
{ return m_pcupsPrintFile( pPrinter, pFileName, pTitle, nOptions, pOptions ); }
- const char* cupsGetPPD( const char* pPrinter );
+ rtl::OString cupsGetPPD( const char* pPrinter );
int cupsMarkOptions(ppd_file_t* pPPD, int nOptions, cups_option_t* pOptions )
{ return m_pcupsMarkOptions(pPPD, nOptions, pOptions); }
@@ -174,7 +175,8 @@ void* CUPSWrapper::loadSymbol( const char* pSymbol )
}
CUPSWrapper::CUPSWrapper()
- : m_pLib( NULL )
+ : m_pLib( NULL ),
+ m_bPPDThreadRunning( false )
{
#ifdef ENABLE_CUPS
OUString aLib( RTL_CONSTASCII_USTRINGPARAM( "libcups.so.2" ) );
@@ -256,68 +258,113 @@ bool CUPSWrapper::isValid()
return m_pLib != NULL;
}
-static struct GetPPDAttribs
+typedef const char*(*PPDFunction)(const char*);
+struct GetPPDAttribs
{
- const char* (*pFunction)(const char*);
+ PPDFunction m_pFunction;
osl::Condition m_aCondition;
- const char* m_pParameter;
- const char* m_pResult;
+ OString m_aParameter;
+ OString m_aResult;
oslThread m_aThread;
-} *pAttribs = NULL;
+ int m_nRefs;
+ bool* m_pResetRunning;
+ osl::Mutex* m_pSyncMutex;
+
+ GetPPDAttribs( PPDFunction pFn, const char * m_pParameter,
+ bool* pResetRunning, osl::Mutex* pSyncMutex )
+ : m_pFunction( pFn ),
+ m_aParameter( m_pParameter ),
+ m_pResetRunning( pResetRunning ),
+ m_pSyncMutex( pSyncMutex )
+ {
+ m_nRefs = 2;
+ m_aCondition.reset();
+ }
-extern "C" {
- static void getPPDWorker(void*)
+ ~GetPPDAttribs()
{
- pAttribs->m_pResult = pAttribs->pFunction( pAttribs->m_pParameter );
- if( pAttribs->m_aCondition.check() )
+ if( m_aResult.getLength() )
+ unlink( m_aResult.getStr() );
+ }
+
+ void unref()
+ {
+ if( --m_nRefs == 0 )
{
- // timed out, unlink file
- if( pAttribs->m_pResult )
- unlink( pAttribs->m_pResult );
- delete pAttribs;
- pAttribs = NULL;
+ *m_pResetRunning = false;
+ delete this;
}
- else
- pAttribs->m_aCondition.set();
+ }
+
+ void executeCall()
+ {
+ // This CUPS method is not at all thread-safe we need
+ // to dup the pointer to a static buffer it returns ASAP
+ OString aResult = m_pFunction( m_aParameter );
+ MutexGuard aGuard( *m_pSyncMutex );
+ m_aResult = aResult;
+ m_aCondition.set();
+ unref();
+ }
+
+ OString waitResult( TimeValue *pDelay )
+ {
+ m_pSyncMutex->release();
+
+ if (m_aCondition.wait( pDelay ) != Condition::result_ok
+ )
+ {
+ #if OSL_DEBUG_LEVEL > 1
+ fprintf( stderr, "cupsGetPPD %s timed out\n",
+ (const sal_Char *) m_aParameter
+ );
+ #endif
+ }
+ m_pSyncMutex->acquire();
+
+ OString aRetval = m_aResult;
+ m_aResult = OString();
+ unref();
+
+ return aRetval;
+ }
+};
+
+extern "C" {
+ static void getPPDWorker(void* pData)
+ {
+ GetPPDAttribs* pAttribs = (GetPPDAttribs*)pData;
+ pAttribs->executeCall();
}
}
-const char* CUPSWrapper::cupsGetPPD( const char* pPrinter )
+OString CUPSWrapper::cupsGetPPD( const char* pPrinter )
{
- const char* pResult = NULL;
+ OString aResult;
+ m_aGetPPDMutex.acquire();
// if one thread hangs in cupsGetPPD already, don't start another
- if( ! pAttribs )
+ if( ! m_bPPDThreadRunning )
{
- pAttribs = new GetPPDAttribs();
- pAttribs->pFunction = m_pcupsGetPPD;
- pAttribs->m_aCondition.reset();
- pAttribs->m_pParameter = pPrinter;
- pAttribs->m_pResult = NULL;
- pAttribs->m_aThread = osl_createThread( getPPDWorker, NULL );
+ m_bPPDThreadRunning = true;
+ GetPPDAttribs* pAttribs = new GetPPDAttribs( m_pcupsGetPPD,
+ pPrinter,
+ &m_bPPDThreadRunning,
+ &m_aGetPPDMutex );
+
+ oslThread aThread = osl_createThread( getPPDWorker, pAttribs );
TimeValue aValue;
aValue.Seconds = 5;
aValue.Nanosec = 0;
- if( pAttribs->m_aCondition.wait( &aValue ) == Condition::result_ok )
- {
- osl_destroyThread( pAttribs->m_aThread );
- pResult = pAttribs->m_pResult;
- delete pAttribs;
- pAttribs = NULL;
- }
- else
- {
-#if OSL_DEBUG_LEVEL > 1
- fprintf( stderr, "cupsGetPPD %s timed out\n", pPrinter );
-#endif
- // should the thread awake again notify it to clean up itself
- pAttribs->m_aCondition.set();
- osl_destroyThread( pAttribs->m_aThread );
- }
+
+ // NOTE: waitResult release and acquires the GetPPD mutex
+ aResult = pAttribs->waitResult( &aValue );
+ osl_destroyThread( aThread );
}
+ m_aGetPPDMutex.release();
- return pResult;
+ return aResult;
}
static const char* setPasswordCallback( const char* pIn )
@@ -577,20 +624,20 @@ const PPDParser* CUPSManager::createCUPSParser( const OUString& rPrinter )
if( dest_it != m_aCUPSDestMap.end() )
{
cups_dest_t* pDest = ((cups_dest_t*)m_pDests) + dest_it->second;
- const char* pPPDFile = m_pCUPSWrapper->cupsGetPPD( pDest->name );
+ OString aPPDFile = m_pCUPSWrapper->cupsGetPPD( pDest->name );
#if OSL_DEBUG_LEVEL > 1
- fprintf( stderr, "PPD for %s is %s\n", OUStringToOString( aPrinter, osl_getThreadTextEncoding() ).getStr(), pPPDFile );
+ fprintf( stderr, "PPD for %s is %s\n", OUStringToOString( aPrinter, osl_getThreadTextEncoding() ).getStr(), aPPDFile.getStr() );
#endif
- if( pPPDFile )
+ if( aPPDFile.getLength() )
{
rtl_TextEncoding aEncoding = osl_getThreadTextEncoding();
- OUString aFileName( OStringToOUString( pPPDFile, aEncoding ) );
+ OUString aFileName( OStringToOUString( aPPDFile, aEncoding ) );
// update the printer info with context information
- ppd_file_t* pPPD = m_pCUPSWrapper->ppdOpenFile( pPPDFile );
+ ppd_file_t* pPPD = m_pCUPSWrapper->ppdOpenFile( aPPDFile.getStr() );
if( pPPD )
{
// create the new parser
- PPDParser* pCUPSParser = new PPDParser( aFileName );
+ PPDParser* pCUPSParser = new PPDParser( aFileName );
pCUPSParser->m_aFile = rPrinter;
pNewParser = pCUPSParser;
@@ -619,25 +666,29 @@ const PPDParser* CUPSManager::createCUPSParser( const OUString& rPrinter )
}
#if OSL_DEBUG_LEVEL > 1
else
- fprintf( stderr, "ppdOpenFile failed, fallinmg back to generic driver\n" );
+ fprintf( stderr, "ppdOpenFile failed, falling back to generic driver\n" );
#endif
// remove temporary PPD file
- unlink( pPPDFile );
+ unlink( aPPDFile.getStr() );
}
#if OSL_DEBUG_LEVEL > 1
else
- fprintf( stderr, "no dest found for printer %s\n", OUStringToOString( aPrinter, osl_getThreadTextEncoding() ).getStr() );
+ fprintf( stderr, "cupsGetPPD failed, falling back to generic driver\n" );
#endif
}
+ #if OSL_DEBUG_LEVEL > 1
+ else
+ fprintf( stderr, "no dest found for printer %s\n", OUStringToOString( aPrinter, osl_getThreadTextEncoding() ).getStr() );
+ #endif
}
m_aCUPSMutex.release();
}
-#if OSL_DEBUG_LEVEL >1
+ #if OSL_DEBUG_LEVEL >1
else
fprintf( stderr, "could not acquire CUPS mutex !!!\n" );
-#endif
-#endif // ENABLE_CUPS
+ #endif
+ #endif // ENABLE_CUPS
if( ! pNewParser )
{