Update ooo320-m1
[ooovba.git] / vcl / unx / source / app / sm.cxx
blobc5c25a4ebf214490901a6b4d561715c75fbaa9cf
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: sm.cxx,v $
10 * $Revision: 1.33.90.1 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_vcl.hxx"
33 #include <string.h>
34 #include <unistd.h>
35 #include <sys/poll.h>
36 #include <fcntl.h>
38 #include <stdio.h>
40 #include <osl/process.h>
41 #include <osl/security.h>
43 #include <tools/prex.h>
44 #include <X11/Xatom.h>
45 #include <tools/postx.h>
46 #include <sm.hxx>
47 #include <saldata.hxx>
48 #include <saldisp.hxx>
49 #include <salframe.h>
50 #include <vcl/svapp.hxx>
51 #include <vcl/window.hxx>
52 #include <salinst.h>
54 #include <osl/conditn.h>
56 #define USE_SM_EXTENSION
58 #if OSL_DEBUG_LEVEL > 1
59 #include <cstdarg>
60 static bool bFirstAssert = true;
61 #endif
63 #if OSL_DEBUG_LEVEL > 1
64 inline void SMprintf( const char* pFormat, ... )
65 #else
66 inline void SMprintf( const char*, ... )
67 #endif
69 #if OSL_DEBUG_LEVEL > 1
70 FILE* fp = fopen( "/tmp/sessionlog.txt", bFirstAssert ? "w" : "a" );
71 if(!fp) return;
72 bFirstAssert = false;
73 std::va_list ap;
74 va_start( ap, pFormat );
75 vfprintf( fp, pFormat, ap );
76 fclose( fp );
77 va_end( ap );
78 #endif
81 static IceSalSession* pOneInstance = NULL;
83 SalSession* X11SalInstance::CreateSalSession()
85 if( ! pOneInstance )
86 pOneInstance = new IceSalSession();
87 return pOneInstance;
91 * class IceSalSession
94 static X11SalFrame* pOldStyleSaveFrame = NULL;
96 IceSalSession::IceSalSession()
100 IceSalSession::~IceSalSession()
102 if( pOneInstance == this )
103 pOneInstance = NULL;
106 void IceSalSession::queryInteraction()
108 if( ! SessionManagerClient::queryInteraction() )
110 SalSessionInteractionEvent aEvent( false );
111 CallCallback( &aEvent );
115 void IceSalSession::interactionDone()
117 SessionManagerClient::interactionDone();
120 void IceSalSession::saveDone()
122 SessionManagerClient::saveDone();
123 if( pOldStyleSaveFrame )
125 // note: does nothing if not running in generic plugin
126 X11SalFrame::SaveYourselfDone( pOldStyleSaveFrame );
130 bool IceSalSession::cancelShutdown()
132 return false;
135 void IceSalSession::handleOldX11SaveYourself( SalFrame* pFrame )
137 // do this only once
138 if( ! pOldStyleSaveFrame )
140 pOldStyleSaveFrame = static_cast<X11SalFrame*>(pFrame);
141 if( pOneInstance )
143 SalSessionSaveRequestEvent aEvent( true, false );
144 pOneInstance->CallCallback( &aEvent );
149 extern "C" void SAL_CALL ICEConnectionWorker( void* );
151 class ICEConnectionObserver
153 friend void SAL_CALL ICEConnectionWorker(void*);
154 static BOOL bIsWatching;
155 static void ICEWatchProc( IceConn connection, IcePointer client_data,
156 Bool opening, IcePointer* watch_data );
158 static struct pollfd* pFilehandles;
159 static IceConn* pConnections;
160 static int nConnections;
161 static int nWakeupFiles[2];
162 static oslMutex ICEMutex;
163 static oslThread ICEThread;
164 public:
166 static void activate();
167 static void deactivate();
168 static void lock();
169 static void unlock();
170 static void wakeup();
174 SmcConn SessionManagerClient::aSmcConnection = NULL;
175 ByteString SessionManagerClient::aClientID;
176 BOOL ICEConnectionObserver::bIsWatching = FALSE;
177 struct pollfd* ICEConnectionObserver::pFilehandles = NULL;
178 IceConn* ICEConnectionObserver::pConnections = NULL;
179 int ICEConnectionObserver::nConnections = 0;
180 oslMutex ICEConnectionObserver::ICEMutex = NULL;
181 oslThread ICEConnectionObserver::ICEThread = NULL;
182 int ICEConnectionObserver::nWakeupFiles[2] = { 0, 0 };
184 // HACK
185 bool SessionManagerClient::bDocSaveDone = false;
188 static SmProp* pSmProps = NULL;
189 static SmProp** ppSmProps = NULL;
190 static int nSmProps = 0;
191 static unsigned char *pSmRestartHint = NULL;
194 static void BuildSmPropertyList()
196 if( ! pSmProps )
198 ByteString aExec( SessionManagerClient::getExecName(), osl_getThreadTextEncoding() );
200 nSmProps = 5;
201 pSmProps = new SmProp[ nSmProps ];
203 pSmProps[ 0 ].name = const_cast<char*>(SmCloneCommand);
204 pSmProps[ 0 ].type = const_cast<char*>(SmLISTofARRAY8);
205 pSmProps[ 0 ].num_vals = 1;
206 pSmProps[ 0 ].vals = new SmPropValue;
207 pSmProps[ 0 ].vals->length = aExec.Len()+1;
208 pSmProps[ 0 ].vals->value = strdup( aExec.GetBuffer() );
210 pSmProps[ 1 ].name = const_cast<char*>(SmProgram);
211 pSmProps[ 1 ].type = const_cast<char*>(SmARRAY8);
212 pSmProps[ 1 ].num_vals = 1;
213 pSmProps[ 1 ].vals = new SmPropValue;
214 pSmProps[ 1 ].vals->length = aExec.Len()+1;
215 pSmProps[ 1 ].vals->value = strdup( aExec.GetBuffer() );
217 pSmProps[ 2 ].name = const_cast<char*>(SmRestartCommand);
218 pSmProps[ 2 ].type = const_cast<char*>(SmLISTofARRAY8);
219 pSmProps[ 2 ].num_vals = 3;
220 pSmProps[ 2 ].vals = new SmPropValue[3];
221 pSmProps[ 2 ].vals[0].length = aExec.Len()+1;
222 pSmProps[ 2 ].vals[0].value = strdup( aExec.GetBuffer() );
223 ByteString aRestartOption( "-session=" );
224 aRestartOption.Append( SessionManagerClient::getSessionID() );
225 pSmProps[ 2 ].vals[1].length = aRestartOption.Len()+1;
226 pSmProps[ 2 ].vals[1].value = strdup( aRestartOption.GetBuffer() );
227 ByteString aRestartOptionNoLogo( "-nologo" );
228 pSmProps[ 2 ].vals[2].length = aRestartOptionNoLogo.Len()+1;
229 pSmProps[ 2 ].vals[2].value = strdup( aRestartOptionNoLogo.GetBuffer() );
231 rtl::OUString aUserName;
232 rtl::OString aUser;
233 oslSecurity aSec = osl_getCurrentSecurity();
234 if( aSec )
236 osl_getUserName( aSec, &aUserName.pData );
237 aUser = rtl::OUStringToOString( aUserName, osl_getThreadTextEncoding() );
238 osl_freeSecurityHandle( aSec );
241 pSmProps[ 3 ].name = const_cast<char*>(SmUserID);
242 pSmProps[ 3 ].type = const_cast<char*>(SmARRAY8);
243 pSmProps[ 3 ].num_vals = 1;
244 pSmProps[ 3 ].vals = new SmPropValue;
245 pSmProps[ 3 ].vals->value = strdup( aUser.getStr() );
246 pSmProps[ 3 ].vals->length = strlen( (char *)pSmProps[ 3 ].vals->value )+1;
248 pSmProps[ 4 ].name = const_cast<char*>(SmRestartStyleHint);
249 pSmProps[ 4 ].type = const_cast<char*>(SmCARD8);
250 pSmProps[ 4 ].num_vals = 1;
251 pSmProps[ 4 ].vals = new SmPropValue;
252 pSmProps[ 4 ].vals->value = malloc(1);
253 pSmRestartHint = (unsigned char *)pSmProps[ 4 ].vals->value;
254 *pSmRestartHint = SmRestartIfRunning;
255 pSmProps[ 4 ].vals->length = 1;
257 ppSmProps = new SmProp*[ nSmProps ];
258 for( int i = 0; i < nSmProps; i++ )
259 ppSmProps[ i ] = &pSmProps[i];
263 bool SessionManagerClient::checkDocumentsSaved()
265 return bDocSaveDone;
268 IMPL_STATIC_LINK( SessionManagerClient, SaveYourselfHdl, void*, EMPTYARG )
270 SMprintf( "posting save documents event shutdown = %s\n", (pThis!=0) ? "true" : "false" );
272 static bool bFirstShutdown=true;
273 if (pThis != 0 && bFirstShutdown) //first shutdown request
275 bFirstShutdown = false;
277 If we have no actual frames open, e.g. we launched a quickstarter,
278 and then shutdown all our frames leaving just a quickstarter running,
279 then we don't want to launch an empty toplevel frame on the next
280 start. (The job of scheduling the restart of the quick-starter is a
281 task of the quick-starter)
283 *pSmRestartHint = SmRestartNever;
284 const std::list< SalFrame* >& rFrames = GetX11SalData()->GetDisplay()->getFrames();
285 for( std::list< SalFrame* >::const_iterator it = rFrames.begin(); it != rFrames.end(); ++it )
287 Window *pWindow = (*it)->GetWindow();
288 if (pWindow && pWindow->IsVisible())
290 *pSmRestartHint = SmRestartIfRunning;
291 break;
296 if( pOneInstance )
298 SalSessionSaveRequestEvent aEvent( pThis != 0, false );
299 pOneInstance->CallCallback( &aEvent );
301 else
302 saveDone();
304 return 0;
307 IMPL_STATIC_LINK_NOINSTANCE( SessionManagerClient, InteractionHdl, void*, EMPTYARG )
309 SMprintf( "interaction link\n" );
310 if( pOneInstance )
312 SalSessionInteractionEvent aEvent( true );
313 pOneInstance->CallCallback( &aEvent );
316 return 0;
319 IMPL_STATIC_LINK_NOINSTANCE( SessionManagerClient, ShutDownCancelHdl, void*, EMPTYARG )
321 SMprintf( "shutdown cancel\n" );
322 if( pOneInstance )
324 SalSessionShutdownCancelEvent aEvent;
325 pOneInstance->CallCallback( &aEvent );
328 return 0;
331 void SessionManagerClient::SaveYourselfProc(
332 SmcConn,
333 SmPointer,
334 int save_type,
335 Bool shutdown,
336 int interact_style,
337 Bool
340 SMprintf( "Session: save yourself, save_type = %s, shutdown = %s, interact_style = %s, fast = %s\n",
341 save_type == SmSaveLocal ? "SmcSaveLocal" :
342 ( save_type == SmSaveGlobal ? "SmcSaveGlobal" :
343 ( save_type == SmSaveBoth ? "SmcSaveBoth" : "<unknown>" ) ),
344 shutdown ? "true" : "false",
345 interact_style == SmInteractStyleNone ? "SmInteractStyleNone" :
346 ( interact_style == SmInteractStyleErrors ? "SmInteractStyleErrors" :
347 ( interact_style == SmInteractStyleAny ? "SmInteractStyleAny" : "<unknown>" ) ),
348 false ? "true" : "false"
350 BuildSmPropertyList();
351 #ifdef USE_SM_EXTENSION
352 bDocSaveDone = false;
353 /* #i49875# some session managers send a "die" message if the
354 * saveDone does not come early enough for their convenience
355 * this can occasionally happen on startup, especially the first
356 * startup. So shortcut the "not shutting down" case since the
357 * upper layers are currently not interested in that event anyway.
359 if( ! shutdown )
361 SessionManagerClient::saveDone();
362 return;
364 Application::PostUserEvent( STATIC_LINK( (void*)(shutdown ? 0xffffffff : 0x0), SessionManagerClient, SaveYourselfHdl ) );
365 SMprintf( "waiting for save yourself event to be processed\n" );
366 #endif
369 IMPL_STATIC_LINK_NOINSTANCE( SessionManagerClient, ShutDownHdl, void*, EMPTYARG )
371 const std::list< SalFrame* >& rFrames = GetX11SalData()->GetDisplay()->getFrames();
372 SMprintf( rFrames.begin() != rFrames.end() ? "shutdown on first frame\n" : "shutdown event but no frame\n" );
373 if( rFrames.begin() != rFrames.end() )
374 rFrames.front()->CallCallback( SALEVENT_SHUTDOWN, 0 );
375 return 0;
378 void SessionManagerClient::DieProc(
379 SmcConn connection,
380 SmPointer
383 SMprintf( "Session: die\n" );
384 if( connection == aSmcConnection )
386 Application::PostUserEvent( STATIC_LINK( NULL, SessionManagerClient, ShutDownHdl ) );
387 SMprintf( "waiting for shutdown event to be processed\n" );
391 void SessionManagerClient::SaveCompleteProc(
392 SmcConn,
393 SmPointer
396 SMprintf( "Session: save complete\n" );
399 void SessionManagerClient::ShutdownCanceledProc(
400 SmcConn connection,
401 SmPointer )
403 SMprintf( "Session: shutdown canceled\n" );
404 if( connection == aSmcConnection )
405 Application::PostUserEvent( STATIC_LINK( NULL, SessionManagerClient, ShutDownCancelHdl ) );
408 void SessionManagerClient::InteractProc(
409 SmcConn connection,
410 SmPointer )
412 SMprintf( "Session: interaction request completed\n" );
413 if( connection == aSmcConnection )
414 Application::PostUserEvent( STATIC_LINK( NULL, SessionManagerClient, InteractionHdl ) );
417 void SessionManagerClient::saveDone()
419 if( aSmcConnection )
421 ICEConnectionObserver::lock();
422 SmcSetProperties( aSmcConnection, nSmProps, ppSmProps );
423 SmcSaveYourselfDone( aSmcConnection, True );
424 SMprintf( "sent SaveYourselfDone SmRestartHint of %d\n", *pSmRestartHint );
425 bDocSaveDone = true;
426 ICEConnectionObserver::unlock();
431 void SessionManagerClient::open()
433 static SmcCallbacks aCallbacks;
435 #ifdef USE_SM_EXTENSION
436 // this is the way Xt does it, so we can too
437 if( ! aSmcConnection && getenv( "SESSION_MANAGER" ) )
439 char aErrBuf[1024];
440 ICEConnectionObserver::activate();
441 ICEConnectionObserver::lock();
443 char* pClientID = NULL;
444 const ByteString& rPrevId( getPreviousSessionID() );
446 aCallbacks.save_yourself.callback = SaveYourselfProc;
447 aCallbacks.save_yourself.client_data = NULL;
448 aCallbacks.die.callback = DieProc;
449 aCallbacks.die.client_data = NULL;
450 aCallbacks.save_complete.callback = SaveCompleteProc;
451 aCallbacks.save_complete.client_data = NULL;
452 aCallbacks.shutdown_cancelled.callback = ShutdownCanceledProc;
453 aCallbacks.shutdown_cancelled.client_data = NULL;
454 aSmcConnection = SmcOpenConnection( NULL,
455 NULL,
456 SmProtoMajor,
457 SmProtoMinor,
458 SmcSaveYourselfProcMask |
459 SmcDieProcMask |
460 SmcSaveCompleteProcMask |
461 SmcShutdownCancelledProcMask ,
462 &aCallbacks,
463 rPrevId.Len() ? const_cast<char*>(rPrevId.GetBuffer()) : NULL,
464 &pClientID,
465 sizeof( aErrBuf ),
466 aErrBuf );
467 if( ! aSmcConnection )
468 SMprintf( "SmcOpenConnection failed: %s\n", aErrBuf );
469 else
470 SMprintf( "SmcOpenConnection succeeded, client ID is \"%s\"\n", pClientID );
471 aClientID = ByteString( pClientID );
472 free( pClientID );
473 pClientID = NULL;
474 ICEConnectionObserver::unlock();
476 SalDisplay* pDisp = GetX11SalData()->GetDisplay();
477 if( pDisp->GetDrawable( pDisp->GetDefaultScreenNumber() ) && aClientID.Len() )
479 XChangeProperty( pDisp->GetDisplay(),
480 pDisp->GetDrawable( pDisp->GetDefaultScreenNumber() ),
481 XInternAtom( pDisp->GetDisplay(), "SM_CLIENT_ID", False ),
482 XA_STRING,
484 PropModeReplace,
485 (unsigned char*)aClientID.GetBuffer(),
486 aClientID.Len()
490 else if( ! aSmcConnection )
491 SMprintf( "no SESSION_MANAGER\n" );
492 #endif
495 const ByteString& SessionManagerClient::getSessionID()
497 return aClientID;
500 void SessionManagerClient::close()
502 if( aSmcConnection )
504 #ifdef USE_SM_EXTENSION
505 ICEConnectionObserver::lock();
506 SMprintf( "attempting SmcCloseConnection\n" );
507 SmcCloseConnection( aSmcConnection, 0, NULL );
508 SMprintf( "SmcConnection closed\n" );
509 ICEConnectionObserver::unlock();
510 ICEConnectionObserver::deactivate();
511 #endif
512 aSmcConnection = NULL;
516 bool SessionManagerClient::queryInteraction()
518 bool bRet = false;
519 if( aSmcConnection )
521 ICEConnectionObserver::lock();
522 if( SmcInteractRequest( aSmcConnection, SmDialogNormal, InteractProc, NULL ) )
523 bRet = true;
524 ICEConnectionObserver::unlock();
526 return bRet;
529 void SessionManagerClient::interactionDone()
531 if( aSmcConnection )
533 ICEConnectionObserver::lock();
534 SmcInteractDone( aSmcConnection, False );
535 ICEConnectionObserver::unlock();
540 String SessionManagerClient::getExecName()
542 rtl::OUString aExec, aSysExec;
543 osl_getExecutableFile( &aExec.pData );
544 osl_getSystemPathFromFileURL( aExec.pData, &aSysExec.pData );
546 int nPos = aSysExec.indexOf( rtl::OUString::createFromAscii( ".bin" ) );
547 if( nPos != -1 )
548 aSysExec = aSysExec.copy( 0, nPos );
549 return aSysExec;
553 const ByteString& SessionManagerClient::getPreviousSessionID()
555 static ByteString aPrevId;
557 int nCommands = osl_getCommandArgCount();
558 for( int i = 0; i < nCommands; i++ )
560 ::rtl::OUString aArg;
561 osl_getCommandArg( i, &aArg.pData );
562 if( aArg.compareToAscii( "-session=", 9 ) == 0 )
564 aPrevId = ByteString( ::rtl::OUStringToOString( aArg.copy( 9 ), osl_getThreadTextEncoding() ) );
565 break;
568 SMprintf( "previous ID = \"%s\"\n", aPrevId.GetBuffer() );
569 return aPrevId;
572 void ICEConnectionObserver::lock()
574 osl_acquireMutex( ICEMutex );
577 void ICEConnectionObserver::unlock()
579 osl_releaseMutex( ICEMutex );
582 void ICEConnectionObserver::activate()
584 if( ! bIsWatching )
586 nWakeupFiles[0] = nWakeupFiles[1] = 0;
587 ICEMutex = osl_createMutex();
588 bIsWatching = TRUE;
589 #ifdef USE_SM_EXTENSION
590 IceAddConnectionWatch( ICEWatchProc, NULL );
591 #endif
595 void ICEConnectionObserver::deactivate()
597 if( bIsWatching )
599 lock();
600 bIsWatching = FALSE;
601 #ifdef USE_SM_EXTENSION
602 IceRemoveConnectionWatch( ICEWatchProc, NULL );
603 #endif
604 nConnections = 0;
605 if( ICEThread )
607 osl_terminateThread( ICEThread );
608 wakeup();
610 unlock();
611 if( ICEThread )
613 osl_joinWithThread( ICEThread );
614 osl_destroyThread( ICEThread );
615 close( nWakeupFiles[1] );
616 close( nWakeupFiles[0] );
617 ICEThread = NULL;
619 osl_destroyMutex( ICEMutex );
620 ICEMutex = NULL;
624 void ICEConnectionObserver::wakeup()
626 char cChar = 'w';
627 write( nWakeupFiles[1], &cChar, 1 );
630 void ICEConnectionWorker( void* )
632 #ifdef USE_SM_EXTENSION
633 while( osl_scheduleThread(ICEConnectionObserver::ICEThread) && ICEConnectionObserver::nConnections )
635 ICEConnectionObserver::lock();
636 int nConnectionsBefore = ICEConnectionObserver::nConnections;
637 int nBytes = sizeof( struct pollfd )*(nConnectionsBefore+1);
638 struct pollfd* pLocalFD = (struct pollfd*)rtl_allocateMemory( nBytes );
639 rtl_copyMemory( pLocalFD, ICEConnectionObserver::pFilehandles, nBytes );
640 ICEConnectionObserver::unlock();
642 int nRet = poll( pLocalFD,nConnectionsBefore+1,-1 );
643 bool bWakeup = (pLocalFD[0].revents & POLLIN);
644 rtl_freeMemory( pLocalFD );
646 if( nRet < 1 )
647 continue;
649 // clear wakeup pipe
650 if( bWakeup )
652 char buf[4];
653 while( read( ICEConnectionObserver::nWakeupFiles[0], buf, sizeof( buf ) ) > 0 )
655 SMprintf( "file handles active in wakeup: %d\n", nRet );
656 if( nRet == 1 )
657 continue;
660 // check fd's after we obtained the lock
661 ICEConnectionObserver::lock();
662 if( ICEConnectionObserver::nConnections > 0 && ICEConnectionObserver::nConnections == nConnectionsBefore )
664 nRet = poll( ICEConnectionObserver::pFilehandles+1, ICEConnectionObserver::nConnections, 0 );
665 if( nRet > 0 )
667 SMprintf( "IceProcessMessages\n" );
668 Bool bReply;
669 for( int i = 0; i < ICEConnectionObserver::nConnections; i++ )
670 if( ICEConnectionObserver::pFilehandles[i+1].revents & POLLIN )
671 IceProcessMessages( ICEConnectionObserver::pConnections[i], NULL, &bReply );
674 ICEConnectionObserver::unlock();
676 #endif
677 SMprintf( "shutting donw ICE dispatch thread\n" );
680 void ICEConnectionObserver::ICEWatchProc(
681 IceConn connection,
682 IcePointer,
683 Bool opening,
684 IcePointer*
687 // note: this is a callback function for ICE
688 // this implicitly means that a call into ICE lib is calling this
689 // so the ICEMutex MUST already be locked by the caller
691 #ifdef USE_SM_EXTENSION
692 if( opening )
694 int fd = IceConnectionNumber( connection );
695 nConnections++;
696 pConnections = (IceConn*)rtl_reallocateMemory( pConnections, sizeof( IceConn )*nConnections );
697 pFilehandles = (struct pollfd*)rtl_reallocateMemory( pFilehandles, sizeof( struct pollfd )*(nConnections+1) );
698 pConnections[ nConnections-1 ] = connection;
699 pFilehandles[ nConnections ].fd = fd;
700 pFilehandles[ nConnections ].events = POLLIN;
701 if( nConnections == 1 )
703 if( ! pipe( nWakeupFiles ) )
705 int flags;
706 pFilehandles[0].fd = nWakeupFiles[0];
707 pFilehandles[0].events = POLLIN;
708 // set close-on-exec and nonblock descriptor flag.
709 if ((flags = fcntl (nWakeupFiles[0], F_GETFD)) != -1)
711 flags |= FD_CLOEXEC;
712 fcntl (nWakeupFiles[0], F_SETFD, flags);
714 if ((flags = fcntl (nWakeupFiles[0], F_GETFL)) != -1)
716 flags |= O_NONBLOCK;
717 fcntl (nWakeupFiles[0], F_SETFL, flags);
719 // set close-on-exec and nonblock descriptor flag.
720 if ((flags = fcntl (nWakeupFiles[1], F_GETFD)) != -1)
722 flags |= FD_CLOEXEC;
723 fcntl (nWakeupFiles[1], F_SETFD, flags);
725 if ((flags = fcntl (nWakeupFiles[1], F_GETFL)) != -1)
727 flags |= O_NONBLOCK;
728 fcntl (nWakeupFiles[1], F_SETFL, flags);
730 ICEThread = osl_createSuspendedThread( ICEConnectionWorker, NULL );
731 osl_resumeThread( ICEThread );
735 else
737 for( int i = 0; i < nConnections; i++ )
739 if( pConnections[i] == connection )
741 if( i < nConnections-1 )
743 rtl_moveMemory( pConnections+i, pConnections+i+1, sizeof( IceConn )*(nConnections-i-1) );
744 rtl_moveMemory( pFilehandles+i+1, pFilehandles+i+2, sizeof( struct pollfd )*(nConnections-i-1) );
746 nConnections--;
747 pConnections = (IceConn*)rtl_reallocateMemory( pConnections, sizeof( IceConn )*nConnections );
748 pFilehandles = (struct pollfd*)rtl_reallocateMemory( pFilehandles, sizeof( struct pollfd )*(nConnections+1) );
749 break;
752 if( nConnections == 0 && ICEThread )
754 SMprintf( "terminating ICEThread\n" );
755 osl_terminateThread( ICEThread );
756 wakeup();
757 // must release the mutex here
758 osl_releaseMutex( ICEMutex );
759 osl_joinWithThread( ICEThread );
760 osl_destroyThread( ICEThread );
761 close( nWakeupFiles[1] );
762 close( nWakeupFiles[0] );
763 ICEThread = NULL;
766 SMprintf( "ICE connection on %d %s\n",
767 IceConnectionNumber( connection ),
768 opening ? "inserted" : "removed" );
769 SMprintf( "Display connection is %d\n", ConnectionNumber( GetX11SalData()->GetDisplay()->GetDisplay() ) );
770 #endif