bump product version to 5.0.4.1
[LibreOffice.git] / vcl / unx / generic / app / sm.cxx
blob6d2bf82c12e5bfac3c63b884c4d0228a9e847c1f
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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"
22 #include <cassert>
24 #include <string.h>
25 #include <unistd.h>
26 #include <sys/poll.h>
27 #include <fcntl.h>
29 #include <stdio.h>
31 #include <rtl/strbuf.hxx>
33 #include <rtl/process.h>
34 #include <osl/security.h>
35 #include <osl/conditn.h>
37 #include <prex.h>
38 #include <X11/Xatom.h>
39 #include <postx.h>
41 #include <unx/sm.hxx>
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"
52 namespace {
54 class IceSalSession : public SalSession
56 public:
57 IceSalSession() {}
59 private:
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);
74 return 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 );
99 return false;
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;
115 int m_nConnections;
116 IceConn* m_pConnections;
117 int m_nWakeupFiles[2];
118 oslThread m_ICEThread;
119 IceIOErrorHandler m_origIOErrorHandler;
120 IceErrorHandler m_origErrorHandler;
122 void wakeup();
124 public:
125 osl::Mutex m_ICEMutex;
127 ICEConnectionObserver()
128 : m_pFilehandles(NULL)
129 , m_nConnections(0)
130 , m_pConnections(NULL)
131 , m_ICEThread(NULL)
132 , m_origIOErrorHandler(NULL)
133 , m_origErrorHandler(NULL)
135 m_nWakeupFiles[0] = m_nWakeupFiles[1] = 0;
138 void activate();
139 void deactivate();
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
150 extern "C" {
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()
170 if( ! pSmProps )
172 OString aExec(OUStringToOString(SessionManagerClient::getExecName(), osl_getThreadTextEncoding()));
174 nSmProps = 5;
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());
206 OUString aUserName;
207 OString aUser;
208 oslSecurity aSec = osl_getCurrentSecurity();
209 if( aSec )
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;
270 break;
275 if( m_pSession )
277 SalSessionSaveRequestEvent aEvent( shutdown, false );
278 m_pSession->CallCallback( &aEvent );
280 else
281 saveDone();
283 return 0;
286 IMPL_STATIC_LINK_NOARG( SessionManagerClient, InteractionHdl )
288 SAL_INFO("vcl.sm", "interaction link");
289 if( m_pSession )
291 SalSessionInteractionEvent aEvent( true );
292 m_pSession->CallCallback( &aEvent );
295 return 0;
298 IMPL_STATIC_LINK_NOARG( SessionManagerClient, ShutDownCancelHdl )
300 SAL_INFO("vcl.sm", "shutdown cancel");
301 if( m_pSession )
303 SalSessionShutdownCancelEvent aEvent;
304 m_pSession->CallCallback( &aEvent );
307 return 0;
310 void SessionManagerClient::SaveYourselfProc(
311 SmcConn,
312 SmPointer,
313 int save_type,
314 Bool shutdown,
315 int interact_style,
316 Bool
319 SAL_INFO("vcl.sm", "Session: save yourself, "
320 "save_type "
321 " local: " << (save_type == SmSaveLocal) <<
322 " global: " << (save_type == SmSaveGlobal) <<
323 " both: " << (save_type == SmSaveBoth) <<
324 " shutdown: " << shutdown <<
325 " interact_style: "
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.
337 if( ! shutdown )
339 SessionManagerClient::saveDone();
340 return;
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 )
350 if( m_pSession )
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 );
360 return 0;
363 void SessionManagerClient::DieProc(
364 SmcConn connection,
365 SmPointer
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(
377 SmcConn,
378 SmPointer
381 SAL_INFO("vcl.sm", "Session: save complete");
384 void SessionManagerClient::ShutdownCanceledProc(
385 SmcConn connection,
386 SmPointer )
388 SAL_INFO("vcl.sm", "Session: shutdown canceled" );
389 if( connection == m_pSmcConnection )
390 Application::PostUserEvent( LINK( NULL, SessionManagerClient, ShutDownCancelHdl ) );
393 void SessionManagerClient::InteractProc(
394 SmcConn connection,
395 SmPointer )
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;
440 char aErrBuf[1024];
441 m_pSmcConnection = SmcOpenConnection( NULL,
442 NULL,
443 SmProtoMajor,
444 SmProtoMinor,
445 SmcSaveYourselfProcMask |
446 SmcDieProcMask |
447 SmcSaveCompleteProcMask |
448 SmcShutdownCancelledProcMask ,
449 &aCallbacks,
450 aPrevId.isEmpty() ? NULL : const_cast<char*>(aPrevId.getStr()),
451 &pClientID,
452 sizeof( aErrBuf ),
453 aErrBuf );
454 if( !m_pSmcConnection )
455 SAL_INFO("vcl.sm", "SmcOpenConnection failed: " << aErrBuf);
456 else
457 SAL_INFO("vcl.sm", "SmcOpenConnection succeeded, client ID is " << pClientID );
458 m_aClientID = OString(pClientID);
459 free( pClientID );
460 pClientID = NULL;
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 ),
469 XA_STRING,
471 PropModeReplace,
472 reinterpret_cast<unsigned char const *>(m_aClientID.getStr()),
473 m_aClientID.getLength()
477 else
479 SAL_INFO("vcl.sm", "no SESSION_MANAGER");
483 OString SessionManagerClient::getSessionID()
485 return m_aClientID;
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()
507 bool bRet = false;
508 if( m_pSmcConnection )
510 assert(m_xICEConnectionObserver);
511 osl::MutexGuard g(m_xICEConnectionObserver->m_ICEMutex);
512 if( SmcInteractRequest( m_pSmcConnection, SmDialogNormal, InteractProc, NULL ) )
513 bRet = true;
515 return bRet;
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") );
536 return aSysExec;
539 OString SessionManagerClient::getPreviousSessionID()
541 OString aPrevId;
543 sal_uInt32 n = rtl_getAppCommandArgCount();
544 for (sal_uInt32 i = 0; i != n; ++i)
546 OUString aArg;
547 rtl_getAppCommandArg( i, &aArg.pData );
548 if(aArg.match("--session="))
550 aPrevId = OUStringToOString(
551 aArg.copy(RTL_CONSTASCII_LENGTH("--session=")),
552 osl_getThreadTextEncoding());
553 break;
557 SAL_INFO("vcl.sm", "previous ID = " << aPrevId.getStr());
558 return aPrevId;
561 void ICEConnectionObserver::activate()
564 * Default handlers call exit, we don't care that strongly if something
565 * happens to fail
567 m_origIOErrorHandler = IceSetIOErrorHandler( IgnoreIceIOErrors );
568 m_origErrorHandler = IceSetErrorHandler( IgnoreIceErrors );
569 IceAddConnectionWatch( ICEWatchProc, this );
572 void ICEConnectionObserver::deactivate()
574 oslThread t;
576 osl::MutexGuard g(m_ICEMutex);
577 IceRemoveConnectionWatch( ICEWatchProc, this );
578 IceSetErrorHandler( m_origErrorHandler );
579 IceSetIOErrorHandler( m_origIOErrorHandler );
580 m_nConnections = 0;
581 t = m_ICEThread;
582 m_ICEThread = NULL;
584 if (t)
586 terminate(t);
590 void ICEConnectionObserver::wakeup()
592 char cChar = 'w';
593 OSL_VERIFY(write(m_nWakeupFiles[1], &cChar, 1) == 1);
596 void ICEConnectionObserver::terminate(oslThread iceThread)
598 osl_terminateThread(iceThread);
599 wakeup();
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 * >(
610 data);
611 for (;;)
613 oslThread t;
615 osl::MutexGuard g(pThis->m_ICEMutex);
616 if (pThis->m_ICEThread == NULL || pThis->m_nConnections == 0)
618 break;
620 t = pThis->m_ICEThread;
622 if (!osl_scheduleThread(t))
624 break;
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 );
641 if( nRet < 1 )
642 continue;
644 // clear wakeup pipe
645 if( bWakeup )
647 char buf[4];
648 while( read( pThis->m_nWakeupFiles[0], buf, sizeof( buf ) ) > 0 )
650 SAL_INFO("vcl.sm", "file handles active in wakeup: " << nRet);
651 if( nRet == 1 )
652 continue;
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 );
660 if( nRet > 0 )
662 SAL_INFO("vcl.sm", "IceProcessMessages");
663 Bool bReply;
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");
673 void ICEWatchProc(
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 * >(
681 client_data);
682 if( opening )
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))
695 int flags;
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)
701 flags |= FD_CLOEXEC;
702 (void)fcntl(pThis->m_nWakeupFiles[0], F_SETFD, flags);
704 if ((flags = fcntl(pThis->m_nWakeupFiles[0], F_GETFL)) != -1)
706 flags |= O_NONBLOCK;
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)
712 flags |= FD_CLOEXEC;
713 (void)fcntl(pThis->m_nWakeupFiles[1], F_SETFD, flags);
715 if ((flags = fcntl(pThis->m_nWakeupFiles[1], F_GETFL)) != -1)
717 flags |= O_NONBLOCK;
718 (void)fcntl(pThis->m_nWakeupFiles[1], F_SETFL, flags);
720 pThis->m_ICEThread = osl_createThread(
721 ICEConnectionWorker, pThis);
725 else // closing
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) ));
739 break;
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();
751 pThis->terminate(t);
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: */