[prev in list] [next in list] [prev in thread] [next in thread] 

List:       kde-core-devel
Subject:    PATCH: make kdeinit exit when it's not needed anymore
From:       David Faure <david () mandrakesoft ! com>
Date:       2000-11-29 22:57:18
[Download RAW message or body]

The attached patches make kdeinit exit 10 seconds after the last
KDE application (DCOP-enabled) exits.

This fixes problems that people are having when using KDE applications
out of KDE (3 or 4 processes are left running after they close the last
KDE application).

In short, dcopserver has a reference counter of registered applications,
which excludes the daemons (klauncher, kded and knotify).

In more details (i.e. for Waldo :), when dcopserver's refcount is 0,
a timer is started, and if it's still the case after 10 seconds
[this is to prevent KDE from exiting on startup :)], then it emits a DCOP
signal "terminateKDE()". I had to add support for dcop signals _sent_
by the DCOPServer.
KLauncher is connected to this signal, and upon receiving it,
it sends a command to kdeinit to tell it to exit. I have tested, and this
effectively kills the daemons as well, as expected.

This is a bit central to KDE, so a bit of peer review can't hurt :-)

--=20
David FAURE, david@mandrakesoft.com, faure@kde.org
http://www.mandrakesoft.com/~david/, http://www.konqueror.org/
KDE, Making The Future of Computing Available Today
See http://www.kde.org/kde1-and-kde2.html for how to set up KDE 2


["dcop.diff" (text/x-c)]

Index: dcopserver.cpp
===================================================================
RCS file: /home/kde/kdelibs/dcop/dcopserver.cpp,v
retrieving revision 1.108
diff -u -p -r1.108 dcopserver.cpp
--- dcopserver.cpp	2000/11/23 00:43:48	1.108
+++ dcopserver.cpp	2000/11/29 22:19:23
@@ -1,5 +1,7 @@
 /*****************************************************************
 
+#include "dcopserver.h"
+
 Copyright (c) 1999,2000 Preston Brown <pbrown@kde.org>
 Copyright (c) 1999,2000 Matthias Ettrich <ettrich@kde.org>
 
@@ -45,6 +47,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE 
 #include <qtextstream.h>
 #include <qdatastream.h>
 #include <qstack.h>
+#include <qtimer.h>
 
 #include <dcopserver.h>
 #include <dcopsignals.h>
@@ -661,7 +664,7 @@ extern "C" int _IceTransNoListen(const c
 #endif
 
 DCOPServer::DCOPServer(bool _only_local)
-    : QObject(0,0), appIds(263), clients(263)
+    : QObject(0,0), appIds(263), clients(263), currentClientNumber(0)
 {
     serverKey = 42;
 
@@ -743,6 +746,9 @@ DCOPServer::DCOPServer(bool _only_local)
     char c = 0;
     write(ready[1], &c, 1); // dcopserver is started
     close(ready[1]);
+
+    m_timer =  new QTimer(this);
+    connect( m_timer, SIGNAL(timeout()), this, SLOT(slotTerminate()) );
 }
 
 DCOPServer::~DCOPServer()
@@ -866,6 +872,13 @@ void DCOPServer::removeConnection( void*
 #ifndef NDEBUG
 	qDebug("DCOP:  unregister '%s'", conn->appId.data() );
 #endif
+        if ( conn->appId.left(9) != "klauncher" && conn->appId != "kded" && \
conn->appId != "knotify" ) +        {
+            currentClientNumber--;
+#ifndef NDEBUG
+            qDebug("DCOP: number of clients is now down to %d", currentClientNumber \
); +#endif
+        }
 	appIds.remove( conn->appId );
 
 	QPtrDictIterator<DCOPConnection> it( clients );
@@ -892,8 +905,20 @@ void DCOPServer::removeConnection( void*
     }
 
     delete conn;
+
+    if ( currentClientNumber == 0 )
+    {
+        m_timer->start( 10000 ); // if within 10 seconds nothing happens, we'll \
terminate +    }
 }
 
+void DCOPServer::slotTerminate()
+{
+    fprintf( stderr, "DCOPServer : slotTerminate() -> sending terminateKDE \
signal.\n" ); +    QByteArray data;
+    dcopSignals->emitSignal(0L /* dcopserver */, "terminateKDE()", data, false);
+}
+
 bool DCOPServer::receive(const QCString &/*app*/, const QCString &obj,
 			 const QCString &fun, const QByteArray& data,
 			 QCString& replyType, QByteArray &replyData,
@@ -922,9 +947,22 @@ bool DCOPServer::receive(const QCString 
 		    appIds.remove( conn->appId );
 		}
 
-#ifndef NDEBUG
 		if ( conn->appId.isNull() )
-		    qDebug("DCOP: register '%s'", app2.data() );
+                {
+                    if ( app2.left(9) != "klauncher" && app2 != "kded" && app2 != \
"knotify" ) +                    {
+                        currentClientNumber++;
+                        m_timer->stop(); // abort termination if we were planning \
one +#ifndef NDEBUG
+                        qDebug("DCOP: register '%s' -> number of clients is now %d", \
app2.data(), currentClientNumber ); +#endif
+                    }
+#ifndef NDEBUG
+                    else
+		      qDebug("DCOP: register '%s'", app2.data() );
+#endif
+                }
+#ifndef NDEBUG
 		else
 		    qDebug("DCOP:  '%s' now known as '%s'", conn->appId.data(), app2.data() );
 #endif
Index: dcopserver.h
===================================================================
RCS file: /home/kde/kdelibs/dcop/dcopserver.h,v
retrieving revision 1.20
diff -u -p -r1.20 dcopserver.h
--- dcopserver.h	2000/09/05 22:05:00	1.20
+++ dcopserver.h	2000/11/29 22:19:24
@@ -46,6 +46,7 @@ class DCOPConnection;
 class DCOPListener;
 class DCOPSignalConnectionList;
 class DCOPSignals;
+class QTimer;
 
 typedef QValueList<QCString> QCStringList;
 
@@ -85,9 +86,9 @@ public:
     void processMessage( IceConn iceConn, int opcode, unsigned long length, Bool \
swap);  void ioError( IceConn iceConn );
 
-    virtual bool receive(const QCString &app, const QCString &obj,
-			 const QCString &fun, const QByteArray& data,
-			 QCString& replyType, QByteArray &replyData, IceConn iceConn);
+    bool receive(const QCString &app, const QCString &obj,
+                 const QCString &fun, const QByteArray& data,
+                 QCString& replyType, QByteArray &replyData, IceConn iceConn);
 
     DCOPConnection *findApp(const QCString &appId);
 
@@ -98,6 +99,7 @@ public:
 private slots:
     void newClient( int socket );
     void processData( int socket );
+    void slotTerminate();
 
 private:
     int majorOpcode;
@@ -106,6 +108,8 @@ private:
     QAsciiDict<DCOPConnection> appIds;
     QPtrDict<DCOPConnection> clients;
     DCOPSignals *dcopSignals;
+    int currentClientNumber;
+    QTimer * m_timer;
 };
 
 extern DCOPServer* the_server;
Index: dcopsignals.cpp
===================================================================
RCS file: /home/kde/kdelibs/dcop/dcopsignals.cpp,v
retrieving revision 1.4
diff -u -p -r1.4 dcopsignals.cpp
--- dcopsignals.cpp	2000/08/03 20:45:14	1.4
+++ dcopsignals.cpp	2000/11/29 22:19:25
@@ -56,7 +56,7 @@ DCOPSignals::emitSignal( DCOPConnection 
       }
       else if (!current->sender.isEmpty())
       {
-	 if (current->sender == conn->appId)
+         if ((conn && current->sender == conn->appId) || (current->sender == \
"DCOPServer"))  doSend = true;
       }
       else
@@ -74,7 +74,7 @@ DCOPSignals::emitSignal( DCOPConnection 
          doSend = false;
       if (doSend)
       {
-         the_server->sendMessage(current->recvConn, conn->appId,
+         the_server->sendMessage(current->recvConn, conn ? conn->appId : \
                QCString("DCOPServer"),
                                  current->recvConn->appId, current->recvObj,
                                  current->slot, data);
       }
Index: dcopsignals.h
===================================================================
RCS file: /home/kde/kdelibs/dcop/dcopsignals.h,v
retrieving revision 1.2
diff -u -p -b -r1.2 dcopsignals.h
--- dcopsignals.h	2000/08/03 20:45:14	1.2
+++ dcopsignals.h	2000/11/29 22:39:14
@@ -61,6 +61,7 @@ public:
    
    /**
     * Client "conn" emits the signal "fun" with "data" as arguments.
+    * conn is 0L if the dcopserver sends the signal itself
     *
     * The emitting object is encoded in "fun".
     *


["klauncher.diff" (text/plain)]

? klauncher.diff
? klauncher.cpp.fix.for.quotes
Index: klauncher.cpp
===================================================================
RCS file: /home/kde/kdelibs/kio/klauncher/klauncher.cpp,v
retrieving revision 1.39
diff -u -p -b -r1.39 klauncher.cpp
--- klauncher.cpp	2000/11/06 10:12:13	1.39
+++ klauncher.cpp	2000/11/29 22:50:32
@@ -132,6 +132,8 @@ KLauncher::KLauncher(int _kdeinitSocket)
    dcopClient()->setNotifications( true );
    connect(dcopClient(), SIGNAL( applicationRegistered( const QCString &)),
            this, SLOT( slotAppRegistered( const QCString &)));
+   dcopClient()->connectDCOPSignal( "DCOPServer", "", "terminateKDE()",
+                                    objId(), "terminateKDE()", false );
 
    QString prefix = locateLocal("socket", "klauncher");
    KTempFile domainname(prefix, QString::fromLatin1(".slave-socket"));
@@ -267,7 +269,17 @@ KLauncher::process(const QCString &fun, 
       IdleSlave *slave;
       for(slave = mSlaveList.first(); slave; slave = mSlaveList.next())
           slave->reparseConfiguration();
+      replyType = "void";
       return true;
+   }
+   else if (fun == "terminateKDE()")
+   {
+      kdDebug() << "KLauncher::process ---> terminateKDE" << endl;
+      klauncher_header request_header;
+      request_header.cmd = LAUNCHER_TERMINATE_KDE;
+      request_header.arg_length = 0;
+      write(kdeinitSocket, &request_header, sizeof(request_header));
+      destruct(0);
    }
    if (KUniqueApplication::process(fun, data, replyType, replyData))
    {
Index: klauncher_cmds.h
===================================================================
RCS file: /home/kde/kdelibs/kio/klauncher/klauncher_cmds.h,v
retrieving revision 1.3
diff -u -p -b -r1.3 klauncher_cmds.h
--- klauncher_cmds.h	2000/02/11 15:28:50	1.3
+++ klauncher_cmds.h	2000/11/29 22:50:32
@@ -90,5 +90,7 @@ typedef struct 
  * char *envs: environment strings.
  * char *tty: tty to redirect stdout/stderr to.
  */ 
+
+#define LAUNCHER_TERMINATE_KDE 7
 
 #endif

["kinit.cpp.diff" (text/x-c)]

Index: kinit.cpp
===================================================================
RCS file: /home/kde/kdelibs/kinit/kinit.cpp,v
retrieving revision 1.49
diff -u -p -r1.49 kinit.cpp
--- kinit.cpp	2000/11/26 23:04:17	1.49
+++ kinit.cpp	2000/11/29 22:50:45
@@ -82,8 +82,12 @@ struct {
   int (*launcher_func)(int);
 } d;
 
+extern "C" {
+int kdeinit_xio_errhandler( Display * );
+}
+
 /*
- * Close fd's which are only usefull for the parent process.
+ * Close fd's which are only useful for the parent process.
  * Restore default signal handlers.
  */
 static void close_fds()
@@ -192,12 +196,17 @@ static pid_t launch(int argc, const char
 
      d.handle = 0;
      if (lib.right(3) == ".la")
+     {
         d.handle = lt_dlopen( lib.data() );
+        if (!d.handle )
+        {
+            const char * ltdlError = lt_dlerror();
+            if ( ltdlError && strcmp(ltdlError,"file not found") )
+                fprintf(stderr, "Could not dlopen library %s: %s\n", lib.data(), \
ltdlError != 0 ? ltdlError : "(null)" ); +        }
+     }
      if (!d.handle )
      {
-        const char * ltdlError = lt_dlerror();
-        if ( ltdlError && strcmp(ltdlError,"file not found") )
-          fprintf(stderr, "Could not dlopen library %s: %s\n", lib.data(), ltdlError \
!= 0 ? ltdlError : "(null)" );  d.result = 2; // Try execing
         write(d.fd[1], &d.result, 1);
 
@@ -549,7 +558,7 @@ static void handle_launcher_request(int 
    }
 
    klauncher_header request_header;
-   char *request_data;
+   char *request_data = 0L;
    int result = read_socket(sock, (char *) &request_header, sizeof(request_header));
    if (result != 0)
    {
@@ -557,16 +566,19 @@ static void handle_launcher_request(int 
          kill_launcher();
       return;
    }
-
-   request_data = (char *) malloc(request_header.arg_length);
 
-   result = read_socket(sock, request_data, request_header.arg_length);
-   if (result != 0)
+   if ( request_header.arg_length != 0 )
    {
-      if (launcher)
-         kill_launcher();
-      free(request_data);
-      return;
+       request_data = (char *) malloc(request_header.arg_length);
+
+       result = read_socket(sock, request_data, request_header.arg_length);
+       if (result != 0)
+       {
+           if (launcher)
+               kill_launcher();
+           free(request_data);
+           return;
+       }
    }
 
    if (request_header.cmd == LAUNCHER_EXEC)
@@ -647,8 +659,14 @@ static void handle_launcher_request(int 
          return;
       }
       setenv( env_name, env_value, 1);
+   }
+   else if (request_header.cmd == LAUNCHER_TERMINATE_KDE)
+   {
+       fprintf(stderr,"kdeinit::LAUNCHER_TERMINATE_KDE -> terminateKDE\n");
+       kdeinit_xio_errhandler( 0L );
    }
-   free(request_data);
+   if (request_data)
+       free(request_data);
 }
 
 static void handle_requests(pid_t waitForPid)
@@ -796,6 +814,7 @@ static void kdeinit_library_path()
    strcpy(sock_file, socketName.data());
 }
 
+/*
 static void output_kmapnotify_path()
 {
    KInstance instance( "kdeinit" );
@@ -813,11 +832,8 @@ static void output_kmapnotify_path()
    }
 
    printf("%s\n", (const char *)output);
-}
-
-extern "C" {
-int kdeinit_xio_errhandler( Display * );
 }
+*/
 
 int kdeinit_xio_errhandler( Display * )
 {
@@ -872,7 +888,7 @@ int main(int argc, char **argv, char **e
    int launch_klauncher = 1;
    int launch_kded = 1;
    int keep_running = 1;
-   int libkmapnotify = 0;
+   //int libkmapnotify = 0;
 
    /** Save arguments first... **/
    char **safe_argv = (char **) malloc( sizeof(char *) * argc);
@@ -887,15 +903,15 @@ int main(int argc, char **argv, char **e
          launch_kded = 0;
       if (strcmp(safe_argv[i], "--exit") == 0)
          keep_running = 0;
-      if (strcmp(safe_argv[i], "--libkmapnotify") == 0)
-         libkmapnotify = 1;
+      //if (strcmp(safe_argv[i], "--libkmapnotify") == 0)
+      //   libkmapnotify = 1;
    }
 
    /** Output path to stdout if libkmapnotify was specified **/
-   if (libkmapnotify) {
+   /*if (libkmapnotify) {
       output_kmapnotify_path();
       return 0;
-   }
+   }*/
 
    /** Make process group leader (for shutting down children later) **/
    if(keep_running)



[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic