1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include "sal/config.h"
31 #include <rtl/strbuf.hxx>
33 #include <rtl/process.h>
34 #include <osl/security.h>
35 #include <osl/conditn.h>
38 #include <X11/Xatom.h>
42 #include <unx/saldata.hxx>
43 #include <unx/saldisp.hxx>
44 #include <unx/salframe.h>
45 #include <unx/salinst.h>
47 #include <vcl/svapp.hxx>
48 #include <vcl/window.hxx>
50 #include "salsession.hxx"
54 class IceSalSession
: public SalSession
60 virtual ~IceSalSession() {}
62 virtual void queryInteraction() SAL_OVERRIDE
;
63 virtual void interactionDone() SAL_OVERRIDE
;
64 virtual void saveDone() SAL_OVERRIDE
;
65 virtual bool cancelShutdown() SAL_OVERRIDE
;
70 SalSession
* X11SalInstance::CreateSalSession()
72 SalSession
* p
= new IceSalSession
;
73 SessionManagerClient::open(p
);
77 void IceSalSession::queryInteraction()
79 if( ! SessionManagerClient::queryInteraction() )
81 SalSessionInteractionEvent
aEvent( false );
82 CallCallback( &aEvent
);
86 void IceSalSession::interactionDone()
88 SessionManagerClient::interactionDone( false );
91 void IceSalSession::saveDone()
93 SessionManagerClient::saveDone();
96 bool IceSalSession::cancelShutdown()
98 SessionManagerClient::interactionDone( true );
102 extern "C" void ICEWatchProc(
103 IceConn ice_conn
, IcePointer client_data
, Bool opening
,
104 IcePointer
* watch_data
);
106 extern "C" void SAL_CALL
ICEConnectionWorker(void * data
);
108 class ICEConnectionObserver
110 friend void ICEWatchProc(IceConn
, IcePointer
, Bool
, IcePointer
*);
112 friend void ICEConnectionWorker(void *);
114 struct pollfd
* m_pFilehandles
;
116 IceConn
* m_pConnections
;
117 int m_nWakeupFiles
[2];
118 oslThread m_ICEThread
;
119 IceIOErrorHandler m_origIOErrorHandler
;
120 IceErrorHandler m_origErrorHandler
;
125 osl::Mutex m_ICEMutex
;
127 ICEConnectionObserver()
128 : m_pFilehandles(NULL
)
130 , m_pConnections(NULL
)
132 , m_origIOErrorHandler(NULL
)
133 , m_origErrorHandler(NULL
)
135 m_nWakeupFiles
[0] = m_nWakeupFiles
[1] = 0;
140 void terminate(oslThread iceThread
);
143 SalSession
* SessionManagerClient::m_pSession
= NULL
;
144 std::unique_ptr
< ICEConnectionObserver
>
145 SessionManagerClient::m_xICEConnectionObserver
;
146 SmcConn
SessionManagerClient::m_pSmcConnection
= NULL
;
147 OString
SessionManagerClient::m_aClientID
;
148 bool SessionManagerClient::m_bDocSaveDone
= false; // HACK
152 static void IgnoreIceErrors(
153 SAL_UNUSED_PARAMETER IceConn
, SAL_UNUSED_PARAMETER Bool
,
154 SAL_UNUSED_PARAMETER
int, SAL_UNUSED_PARAMETER
unsigned long,
155 SAL_UNUSED_PARAMETER
int, SAL_UNUSED_PARAMETER
int,
156 SAL_UNUSED_PARAMETER IcePointer
)
159 static void IgnoreIceIOErrors(SAL_UNUSED_PARAMETER IceConn
) {}
163 static SmProp
* pSmProps
= NULL
;
164 static SmProp
** ppSmProps
= NULL
;
165 static int nSmProps
= 0;
166 static unsigned char *pSmRestartHint
= NULL
;
168 static void BuildSmPropertyList()
172 OString
aExec(OUStringToOString(SessionManagerClient::getExecName(), osl_getThreadTextEncoding()));
175 pSmProps
= new SmProp
[ nSmProps
];
177 pSmProps
[ 0 ].name
= const_cast<char*>(SmCloneCommand
);
178 pSmProps
[ 0 ].type
= const_cast<char*>(SmLISTofARRAY8
);
179 pSmProps
[ 0 ].num_vals
= 1;
180 pSmProps
[ 0 ].vals
= new SmPropValue
;
181 pSmProps
[ 0 ].vals
->length
= aExec
.getLength()+1;
182 pSmProps
[ 0 ].vals
->value
= strdup( aExec
.getStr() );
184 pSmProps
[ 1 ].name
= const_cast<char*>(SmProgram
);
185 pSmProps
[ 1 ].type
= const_cast<char*>(SmARRAY8
);
186 pSmProps
[ 1 ].num_vals
= 1;
187 pSmProps
[ 1 ].vals
= new SmPropValue
;
188 pSmProps
[ 1 ].vals
->length
= aExec
.getLength()+1;
189 pSmProps
[ 1 ].vals
->value
= strdup( aExec
.getStr() );
191 pSmProps
[ 2 ].name
= const_cast<char*>(SmRestartCommand
);
192 pSmProps
[ 2 ].type
= const_cast<char*>(SmLISTofARRAY8
);
193 pSmProps
[ 2 ].num_vals
= 3;
194 pSmProps
[ 2 ].vals
= new SmPropValue
[3];
195 pSmProps
[ 2 ].vals
[0].length
= aExec
.getLength()+1;
196 pSmProps
[ 2 ].vals
[0].value
= strdup( aExec
.getStr() );
197 OStringBuffer aRestartOption
;
198 aRestartOption
.append("--session=");
199 aRestartOption
.append(SessionManagerClient::getSessionID());
200 pSmProps
[ 2 ].vals
[1].length
= aRestartOption
.getLength()+1;
201 pSmProps
[ 2 ].vals
[1].value
= strdup(aRestartOption
.getStr());
202 OString
aRestartOptionNoLogo("--nologo");
203 pSmProps
[ 2 ].vals
[2].length
= aRestartOptionNoLogo
.getLength()+1;
204 pSmProps
[ 2 ].vals
[2].value
= strdup(aRestartOptionNoLogo
.getStr());
208 oslSecurity aSec
= osl_getCurrentSecurity();
211 osl_getUserName( aSec
, &aUserName
.pData
);
212 aUser
= OUStringToOString( aUserName
, osl_getThreadTextEncoding() );
213 osl_freeSecurityHandle( aSec
);
216 pSmProps
[ 3 ].name
= const_cast<char*>(SmUserID
);
217 pSmProps
[ 3 ].type
= const_cast<char*>(SmARRAY8
);
218 pSmProps
[ 3 ].num_vals
= 1;
219 pSmProps
[ 3 ].vals
= new SmPropValue
;
220 pSmProps
[ 3 ].vals
->value
= strdup( aUser
.getStr() );
221 pSmProps
[ 3 ].vals
->length
= rtl_str_getLength( static_cast<char *>(pSmProps
[ 3 ].vals
->value
) )+1;
223 pSmProps
[ 4 ].name
= const_cast<char*>(SmRestartStyleHint
);
224 pSmProps
[ 4 ].type
= const_cast<char*>(SmCARD8
);
225 pSmProps
[ 4 ].num_vals
= 1;
226 pSmProps
[ 4 ].vals
= new SmPropValue
;
227 pSmProps
[ 4 ].vals
->value
= malloc(1);
228 pSmRestartHint
= static_cast<unsigned char *>(pSmProps
[ 4 ].vals
->value
);
229 *pSmRestartHint
= SmRestartIfRunning
;
230 pSmProps
[ 4 ].vals
->length
= 1;
232 ppSmProps
= new SmProp
*[ nSmProps
];
233 for( int i
= 0; i
< nSmProps
; i
++ )
234 ppSmProps
[ i
] = &pSmProps
[i
];
238 bool SessionManagerClient::checkDocumentsSaved()
240 return m_bDocSaveDone
;
243 IMPL_STATIC_LINK( SessionManagerClient
, SaveYourselfHdl
, void*, pStateVal
)
245 // Decode argument smuggled in as void*:
246 sal_uIntPtr nStateVal
= reinterpret_cast< sal_uIntPtr
>(pStateVal
);
247 bool shutdown
= nStateVal
!= 0;
249 SAL_INFO("vcl.sm", "posting save documents event shutdown = " << (shutdown
? "true" : "false" ));
251 static bool bFirstShutdown
=true;
252 if (shutdown
&& bFirstShutdown
) //first shutdown request
254 bFirstShutdown
= false;
256 If we have no actual frames open, e.g. we launched a quickstarter,
257 and then shutdown all our frames leaving just a quickstarter running,
258 then we don't want to launch an empty toplevel frame on the next
259 start. (The job of scheduling the restart of the quick-starter is a
260 task of the quick-starter)
262 *pSmRestartHint
= SmRestartNever
;
263 const std::list
< SalFrame
* >& rFrames
= vcl_sal::getSalDisplay(GetGenericData())->getFrames();
264 for( std::list
< SalFrame
* >::const_iterator it
= rFrames
.begin(); it
!= rFrames
.end(); ++it
)
266 vcl::Window
*pWindow
= (*it
)->GetWindow();
267 if (pWindow
&& pWindow
->IsVisible())
269 *pSmRestartHint
= SmRestartIfRunning
;
277 SalSessionSaveRequestEvent
aEvent( shutdown
, false );
278 m_pSession
->CallCallback( &aEvent
);
286 IMPL_STATIC_LINK_NOARG( SessionManagerClient
, InteractionHdl
)
288 SAL_INFO("vcl.sm", "interaction link");
291 SalSessionInteractionEvent
aEvent( true );
292 m_pSession
->CallCallback( &aEvent
);
298 IMPL_STATIC_LINK_NOARG( SessionManagerClient
, ShutDownCancelHdl
)
300 SAL_INFO("vcl.sm", "shutdown cancel");
303 SalSessionShutdownCancelEvent aEvent
;
304 m_pSession
->CallCallback( &aEvent
);
310 void SessionManagerClient::SaveYourselfProc(
319 SAL_INFO("vcl.sm", "Session: save yourself, "
321 " local: " << (save_type
== SmSaveLocal
) <<
322 " global: " << (save_type
== SmSaveGlobal
) <<
323 " both: " << (save_type
== SmSaveBoth
) <<
324 " shutdown: " << shutdown
<<
326 " SmInteractStyleNone: " << (interact_style
== SmInteractStyleNone
) <<
327 " SmInteractStyleErrors: " << (interact_style
== SmInteractStyleErrors
) <<
328 " SmInteractStyleErrors: " << (interact_style
== SmInteractStyleAny
));
329 BuildSmPropertyList();
330 m_bDocSaveDone
= false;
331 /* #i49875# some session managers send a "die" message if the
332 * saveDone does not come early enough for their convenience
333 * this can occasionally happen on startup, especially the first
334 * startup. So shortcut the "not shutting down" case since the
335 * upper layers are currently not interested in that event anyway.
339 SessionManagerClient::saveDone();
342 // Smuggle argument in as void*:
343 sal_uIntPtr nStateVal
= shutdown
;
344 Application::PostUserEvent( LINK( 0, SessionManagerClient
, SaveYourselfHdl
), reinterpret_cast< void * >(nStateVal
) );
345 SAL_INFO("vcl.sm", "waiting for save yourself event to be processed" );
348 IMPL_STATIC_LINK_NOARG( SessionManagerClient
, ShutDownHdl
)
352 SalSessionQuitEvent aEvent
;
353 m_pSession
->CallCallback( &aEvent
);
356 const std::list
< SalFrame
* >& rFrames
= vcl_sal::getSalDisplay(GetGenericData())->getFrames();
357 SAL_INFO("vcl.sm", (rFrames
.begin() != rFrames
.end() ? "shutdown on first frame" : "shutdown event but no frame"));
358 if( rFrames
.begin() != rFrames
.end() )
359 rFrames
.front()->CallCallback( SALEVENT_SHUTDOWN
, 0 );
363 void SessionManagerClient::DieProc(
368 SAL_INFO("vcl.sm", "Session: die");
369 if( connection
== m_pSmcConnection
)
371 Application::PostUserEvent( LINK( NULL
, SessionManagerClient
, ShutDownHdl
) );
372 SAL_INFO("vcl.sm", "waiting for shutdown event to be processed" );
376 void SessionManagerClient::SaveCompleteProc(
381 SAL_INFO("vcl.sm", "Session: save complete");
384 void SessionManagerClient::ShutdownCanceledProc(
388 SAL_INFO("vcl.sm", "Session: shutdown canceled" );
389 if( connection
== m_pSmcConnection
)
390 Application::PostUserEvent( LINK( NULL
, SessionManagerClient
, ShutDownCancelHdl
) );
393 void SessionManagerClient::InteractProc(
397 SAL_INFO("vcl.sm", "Session: interaction request completed" );
398 if( connection
== m_pSmcConnection
)
399 Application::PostUserEvent( LINK( NULL
, SessionManagerClient
, InteractionHdl
) );
402 void SessionManagerClient::saveDone()
404 if( m_pSmcConnection
)
406 assert(m_xICEConnectionObserver
);
407 osl::MutexGuard
g(m_xICEConnectionObserver
->m_ICEMutex
);
408 SmcSetProperties( m_pSmcConnection
, nSmProps
, ppSmProps
);
409 SmcSaveYourselfDone( m_pSmcConnection
, True
);
410 SAL_INFO("vcl.sm", "sent SaveYourselfDone SmRestartHint of " << *pSmRestartHint
);
411 m_bDocSaveDone
= true;
415 void SessionManagerClient::open(SalSession
* pSession
)
417 assert(!m_pSession
&& !m_xICEConnectionObserver
&& !m_pSmcConnection
);
418 // must only be called once
419 m_pSession
= pSession
;
420 // This is the way Xt does it, so we can too:
421 if( getenv( "SESSION_MANAGER" ) )
423 m_xICEConnectionObserver
.reset(new ICEConnectionObserver
);
424 m_xICEConnectionObserver
->activate();
427 osl::MutexGuard
g(m_xICEConnectionObserver
->m_ICEMutex
);
429 static SmcCallbacks aCallbacks
; // does this need to be static?
430 aCallbacks
.save_yourself
.callback
= SaveYourselfProc
;
431 aCallbacks
.save_yourself
.client_data
= NULL
;
432 aCallbacks
.die
.callback
= DieProc
;
433 aCallbacks
.die
.client_data
= NULL
;
434 aCallbacks
.save_complete
.callback
= SaveCompleteProc
;
435 aCallbacks
.save_complete
.client_data
= NULL
;
436 aCallbacks
.shutdown_cancelled
.callback
= ShutdownCanceledProc
;
437 aCallbacks
.shutdown_cancelled
.client_data
= NULL
;
438 OString
aPrevId(getPreviousSessionID());
439 char* pClientID
= NULL
;
441 m_pSmcConnection
= SmcOpenConnection( NULL
,
445 SmcSaveYourselfProcMask
|
447 SmcSaveCompleteProcMask
|
448 SmcShutdownCancelledProcMask
,
450 aPrevId
.isEmpty() ? NULL
: const_cast<char*>(aPrevId
.getStr()),
454 if( !m_pSmcConnection
)
455 SAL_INFO("vcl.sm", "SmcOpenConnection failed: " << aErrBuf
);
457 SAL_INFO("vcl.sm", "SmcOpenConnection succeeded, client ID is " << pClientID
);
458 m_aClientID
= OString(pClientID
);
463 SalDisplay
* pDisp
= vcl_sal::getSalDisplay(GetGenericData());
464 if( pDisp
->GetDrawable(pDisp
->GetDefaultXScreen()) && !m_aClientID
.isEmpty() )
466 XChangeProperty( pDisp
->GetDisplay(),
467 pDisp
->GetDrawable( pDisp
->GetDefaultXScreen() ),
468 XInternAtom( pDisp
->GetDisplay(), "SM_CLIENT_ID", False
),
472 reinterpret_cast<unsigned char const *>(m_aClientID
.getStr()),
473 m_aClientID
.getLength()
479 SAL_INFO("vcl.sm", "no SESSION_MANAGER");
483 OString
SessionManagerClient::getSessionID()
488 void SessionManagerClient::close()
490 if( m_pSmcConnection
)
492 assert(m_xICEConnectionObserver
);
494 osl::MutexGuard
g(m_xICEConnectionObserver
->m_ICEMutex
);
495 SAL_INFO("vcl.sm", "attempting SmcCloseConnection");
496 SmcCloseConnection( m_pSmcConnection
, 0, NULL
);
497 SAL_INFO("vcl.sm", "SmcConnection closed");
499 m_xICEConnectionObserver
->deactivate();
500 m_xICEConnectionObserver
.reset();
501 m_pSmcConnection
= NULL
;
505 bool SessionManagerClient::queryInteraction()
508 if( m_pSmcConnection
)
510 assert(m_xICEConnectionObserver
);
511 osl::MutexGuard
g(m_xICEConnectionObserver
->m_ICEMutex
);
512 if( SmcInteractRequest( m_pSmcConnection
, SmDialogNormal
, InteractProc
, NULL
) )
518 void SessionManagerClient::interactionDone( bool bCancelShutdown
)
520 if( m_pSmcConnection
)
522 assert(m_xICEConnectionObserver
);
523 osl::MutexGuard
g(m_xICEConnectionObserver
->m_ICEMutex
);
524 SmcInteractDone( m_pSmcConnection
, bCancelShutdown
? True
: False
);
528 OUString
SessionManagerClient::getExecName()
530 OUString aExec
, aSysExec
;
531 osl_getExecutableFile( &aExec
.pData
);
532 osl_getSystemPathFromFileURL( aExec
.pData
, &aSysExec
.pData
);
534 if( aSysExec
.endsWith(".bin") )
535 aSysExec
= aSysExec
.copy( 0, aSysExec
.getLength() - RTL_CONSTASCII_LENGTH(".bin") );
539 OString
SessionManagerClient::getPreviousSessionID()
543 sal_uInt32 n
= rtl_getAppCommandArgCount();
544 for (sal_uInt32 i
= 0; i
!= n
; ++i
)
547 rtl_getAppCommandArg( i
, &aArg
.pData
);
548 if(aArg
.match("--session="))
550 aPrevId
= OUStringToOString(
551 aArg
.copy(RTL_CONSTASCII_LENGTH("--session=")),
552 osl_getThreadTextEncoding());
557 SAL_INFO("vcl.sm", "previous ID = " << aPrevId
.getStr());
561 void ICEConnectionObserver::activate()
564 * Default handlers call exit, we don't care that strongly if something
567 m_origIOErrorHandler
= IceSetIOErrorHandler( IgnoreIceIOErrors
);
568 m_origErrorHandler
= IceSetErrorHandler( IgnoreIceErrors
);
569 IceAddConnectionWatch( ICEWatchProc
, this );
572 void ICEConnectionObserver::deactivate()
576 osl::MutexGuard
g(m_ICEMutex
);
577 IceRemoveConnectionWatch( ICEWatchProc
, this );
578 IceSetErrorHandler( m_origErrorHandler
);
579 IceSetIOErrorHandler( m_origIOErrorHandler
);
590 void ICEConnectionObserver::wakeup()
593 OSL_VERIFY(write(m_nWakeupFiles
[1], &cChar
, 1) == 1);
596 void ICEConnectionObserver::terminate(oslThread iceThread
)
598 osl_terminateThread(iceThread
);
600 osl_joinWithThread(iceThread
);
601 osl_destroyThread(iceThread
);
602 close(m_nWakeupFiles
[1]);
603 close(m_nWakeupFiles
[0]);
606 void ICEConnectionWorker(void * data
)
608 osl::Thread::setName("ICEConnectionWorker");
609 ICEConnectionObserver
* pThis
= static_cast< ICEConnectionObserver
* >(
615 osl::MutexGuard
g(pThis
->m_ICEMutex
);
616 if (pThis
->m_ICEThread
== NULL
|| pThis
->m_nConnections
== 0)
620 t
= pThis
->m_ICEThread
;
622 if (!osl_scheduleThread(t
))
627 int nConnectionsBefore
;
628 struct pollfd
* pLocalFD
;
630 osl::MutexGuard
g(pThis
->m_ICEMutex
);
631 nConnectionsBefore
= pThis
->m_nConnections
;
632 int nBytes
= sizeof( struct pollfd
)*(nConnectionsBefore
+1);
633 pLocalFD
= static_cast<struct pollfd
*>(rtl_allocateMemory( nBytes
));
634 memcpy( pLocalFD
, pThis
->m_pFilehandles
, nBytes
);
637 int nRet
= poll( pLocalFD
,nConnectionsBefore
+1,-1 );
638 bool bWakeup
= (pLocalFD
[0].revents
& POLLIN
);
639 rtl_freeMemory( pLocalFD
);
648 while( read( pThis
->m_nWakeupFiles
[0], buf
, sizeof( buf
) ) > 0 )
650 SAL_INFO("vcl.sm", "file handles active in wakeup: " << nRet
);
655 // check fd's after we obtained the lock
656 osl::MutexGuard
g(pThis
->m_ICEMutex
);
657 if( pThis
->m_nConnections
> 0 && pThis
->m_nConnections
== nConnectionsBefore
)
659 nRet
= poll( pThis
->m_pFilehandles
+1, pThis
->m_nConnections
, 0 );
662 SAL_INFO("vcl.sm", "IceProcessMessages");
664 for( int i
= 0; i
< pThis
->m_nConnections
; i
++ )
665 if( pThis
->m_pFilehandles
[i
+1].revents
& POLLIN
)
666 IceProcessMessages( pThis
->m_pConnections
[i
], NULL
, &bReply
);
670 SAL_INFO("vcl.sm", "shutting down ICE dispatch thread");
674 IceConn ice_conn
, IcePointer client_data
, Bool opening
,
675 SAL_UNUSED_PARAMETER IcePointer
*)
677 // Note: This is a callback function for ICE; this implicitly means that a
678 // call into ICE lib is calling this, so the m_ICEMutex MUST already be
679 // locked by the caller.
680 ICEConnectionObserver
* pThis
= static_cast< ICEConnectionObserver
* >(
684 int fd
= IceConnectionNumber( ice_conn
);
685 pThis
->m_nConnections
++;
686 pThis
->m_pConnections
= static_cast<IceConn
*>(rtl_reallocateMemory( pThis
->m_pConnections
, sizeof( IceConn
)*pThis
->m_nConnections
));
687 pThis
->m_pFilehandles
= static_cast<struct pollfd
*>(rtl_reallocateMemory( pThis
->m_pFilehandles
, sizeof( struct pollfd
)*(pThis
->m_nConnections
+1) ));
688 pThis
->m_pConnections
[ pThis
->m_nConnections
-1 ] = ice_conn
;
689 pThis
->m_pFilehandles
[ pThis
->m_nConnections
].fd
= fd
;
690 pThis
->m_pFilehandles
[ pThis
->m_nConnections
].events
= POLLIN
;
691 if( pThis
->m_nConnections
== 1 )
693 if (!pipe(pThis
->m_nWakeupFiles
))
696 pThis
->m_pFilehandles
[0].fd
= pThis
->m_nWakeupFiles
[0];
697 pThis
->m_pFilehandles
[0].events
= POLLIN
;
698 // set close-on-exec and nonblock descriptor flag.
699 if ((flags
= fcntl(pThis
->m_nWakeupFiles
[0], F_GETFD
)) != -1)
702 (void)fcntl(pThis
->m_nWakeupFiles
[0], F_SETFD
, flags
);
704 if ((flags
= fcntl(pThis
->m_nWakeupFiles
[0], F_GETFL
)) != -1)
707 (void)fcntl(pThis
->m_nWakeupFiles
[0], F_SETFL
, flags
);
709 // set close-on-exec and nonblock descriptor flag.
710 if ((flags
= fcntl(pThis
->m_nWakeupFiles
[1], F_GETFD
)) != -1)
713 (void)fcntl(pThis
->m_nWakeupFiles
[1], F_SETFD
, flags
);
715 if ((flags
= fcntl(pThis
->m_nWakeupFiles
[1], F_GETFL
)) != -1)
718 (void)fcntl(pThis
->m_nWakeupFiles
[1], F_SETFL
, flags
);
720 pThis
->m_ICEThread
= osl_createThread(
721 ICEConnectionWorker
, pThis
);
727 for( int i
= 0; i
< pThis
->m_nConnections
; i
++ )
729 if( pThis
->m_pConnections
[i
] == ice_conn
)
731 if( i
< pThis
->m_nConnections
-1 )
733 memmove( pThis
->m_pConnections
+i
, pThis
->m_pConnections
+i
+1, sizeof( IceConn
)*(pThis
->m_nConnections
-i
-1) );
734 memmove( pThis
->m_pFilehandles
+i
+1, pThis
->m_pFilehandles
+i
+2, sizeof( struct pollfd
)*(pThis
->m_nConnections
-i
-1) );
736 pThis
->m_nConnections
--;
737 pThis
->m_pConnections
= static_cast<IceConn
*>(rtl_reallocateMemory( pThis
->m_pConnections
, sizeof( IceConn
)*pThis
->m_nConnections
));
738 pThis
->m_pFilehandles
= static_cast<struct pollfd
*>(rtl_reallocateMemory( pThis
->m_pFilehandles
, sizeof( struct pollfd
)*(pThis
->m_nConnections
+1) ));
742 if( pThis
->m_nConnections
== 0 && pThis
->m_ICEThread
)
744 SAL_INFO("vcl.sm", "terminating ICEThread");
745 oslThread t
= pThis
->m_ICEThread
;
746 pThis
->m_ICEThread
= NULL
;
748 // must release the mutex here
749 pThis
->m_ICEMutex
.release();
753 // acquire the mutex again, because the caller does not expect
754 // it to be released when calling into SM
755 pThis
->m_ICEMutex
.acquire();
758 SAL_INFO( "vcl.sm", "ICE connection on " << IceConnectionNumber( ice_conn
) << " " << (opening
? "inserted" : "removed"));
759 SAL_INFO( "vcl.sm", "Display connection is " << ConnectionNumber( vcl_sal::getSalDisplay(GetGenericData())->GetDisplay() ) );
762 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */