Author: lslezak
Date: Fri Jul 18 11:50:38 2008
New Revision: 49244
URL: http://svn.opensuse.org/viewcvs/yast?rev=49244&view=rev
Log:
- finish the service after timeout when the client is not running
Modified:
branches/tmp/lslezak/workshop/core/dbus/SCR_service/DBusServer.cc
branches/tmp/lslezak/workshop/core/dbus/SCR_service/DBusServer.h
Modified: branches/tmp/lslezak/workshop/core/dbus/SCR_service/DBusServer.cc
URL: http://svn.opensuse.org/viewcvs/yast/branches/tmp/lslezak/workshop/core/dbus/SCR_service/DBusServer.cc?rev=49244&r1=49243&r2=49244&view=diff
==============================================================================
--- branches/tmp/lslezak/workshop/core/dbus/SCR_service/DBusServer.cc (original)
+++ branches/tmp/lslezak/workshop/core/dbus/SCR_service/DBusServer.cc Fri Jul 18 11:50:38 2008
@@ -14,11 +14,21 @@
#include
-// nanosleep
+extern "C"
+{
+// nanosleep()
#include
+// stat()
+#include
+}
+
+// ostringstream
+#include <sstream>
+
+static bool finish = false;
-DBusServer::DBusServer()
+DBusServer::DBusServer() : client_pid(0)
{
sa = new ScriptingAgent();
}
@@ -38,6 +48,46 @@
return connection.connect(DBUS_BUS_SYSTEM, "org.opensuse.yast.SCR");
}
+void DBusServer::resetTimer()
+{
+ ::alarm(10);
+}
+
+// NOTE: this is a signal handler, do only really necessary tasks here!
+// be aware of non-reentrant functions!
+void sig_timer(int signal, siginfo_t *info, void *data)
+{
+ if (signal == SIGALRM)
+ {
+ // set the finish flag for the main loop
+ finish = true;
+ }
+}
+
+void DBusServer::registerSignalHandler()
+{
+ struct sigaction new_action, old_action;
+
+ // use sa_sigaction parameter
+ new_action.sa_flags = SA_SIGINFO;
+ new_action.sa_sigaction = &sig_timer;
+ ::sigemptyset(&new_action.sa_mask);
+
+ if (::sigaction(SIGALRM, &new_action, &old_action))
+ {
+ y2error("Cannot register SIGALRM handler!");
+ }
+}
+
+bool DBusServer::canFinish()
+{
+ // no client connected, can exit unconditionally
+ if (client_pid == 0)
+ return true;
+
+ // check if the client is still running
+ return !isProcessRunning(client_pid);
+}
/**
* Server that exposes a method call and waits for it to be called
@@ -53,9 +103,30 @@
// 50 miliseconds
req.tv_nsec = 50000000;
+ registerSignalHandler();
+
// mainloop
while (true)
{
+ // the time is over
+ if (finish)
+ {
+ y2milestone("Timout signal received");
+
+ if (canFinish())
+ {
+ break;
+ }
+ else
+ {
+ // reset the flag
+ finish = false;
+
+ // set a new timer
+ resetTimer();
+ }
+ }
+
// set 100 milisecond timeout
connection.setTimeout(100);
// try reading a message from DBus
@@ -68,6 +139,9 @@
continue;
}
+ // reset the timer when a message is received
+ resetTimer();
+
// create a reply to the message
DBusMsg reply;
@@ -142,6 +216,9 @@
else
#endif
{
+ // remember the client PID
+ client_pid = callerPid(request);
+
YCPValue ret;
if (method == "Read")
@@ -291,6 +368,8 @@
y2milestone("Message processed");
}
+
+ y2milestone("Finishing the DBus service");
}
#ifdef HAVE_POLKIT
@@ -317,3 +396,51 @@
return ret;
}
#endif
+
+
+bool DBusServer::isProcessRunning(pid_t pid)
+{
+ ostringstream sstr;
+ sstr << "/proc/" << pid;
+
+ struct stat stat_result;
+ bool ret = ::stat(sstr.str().c_str(), &stat_result) == 0;
+
+ y2milestone("Process /proc/%d is running: %s", pid, ret ? "true" : "false");
+ return ret;
+}
+
+pid_t DBusServer::callerPid(const DBusMsg &msg)
+{
+ pid_t pid;
+ DBusMsg query;
+
+ // ask the DBus server for the PID of the caller
+ query.createCall("org.freedesktop.DBus", "/org/freedesktop/DBus/Bus",
+ "org.freedesktop.DBus", "GetConnectionUnixProcessID");
+
+ query.addString(msg.sender());
+
+ // send the request
+ DBusMsg reply(connection.call(query));
+
+ // read the answer
+ DBusMessageIter iter;
+ dbus_message_iter_init(reply.getMessage(), &iter);
+
+ int type = dbus_message_iter_get_arg_type(&iter);
+ y2internal("Message type: %d, %c", type, (char)type);
+
+ if (type == DBUS_TYPE_UINT32)
+ {
+ dbus_message_iter_get_basic(&iter, &pid);
+ }
+ else
+ {
+ y2internal("Unexpected type in PID reply %d (%c)", type, (char)type);
+ }
+
+ y2milestone("Message from PID %d", pid);
+
+ return pid;
+}
Modified: branches/tmp/lslezak/workshop/core/dbus/SCR_service/DBusServer.h
URL: http://svn.opensuse.org/viewcvs/yast/branches/tmp/lslezak/workshop/core/dbus/SCR_service/DBusServer.h?rev=49244&r1=49243&r2=49244&view=diff
==============================================================================
--- branches/tmp/lslezak/workshop/core/dbus/SCR_service/DBusServer.h (original)
+++ branches/tmp/lslezak/workshop/core/dbus/SCR_service/DBusServer.h Fri Jul 18 11:50:38 2008
@@ -17,6 +17,12 @@
#include "PolKit.h"
#endif
+extern "C"
+{
+#include
+#include
+}
+
class DBusServer
{
public:
@@ -30,6 +36,7 @@
private:
DBusConn connection;
+ pid_t client_pid;
#ifdef HAVE_POLKIT
PolKit policykit;
@@ -43,6 +50,12 @@
// disable copying
DBusServer(const DBusServer&);
DBusServer& operator=(const DBusServer&);
+
+ void resetTimer();
+ void registerSignalHandler();
+ bool isProcessRunning(pid_t pid);
+ bool canFinish();
+ pid_t callerPid(const DBusMsg &msg);
};
--
To unsubscribe, e-mail: yast-commit+unsubscribe@opensuse.org
For additional commands, e-mail: yast-commit+help@opensuse.org