void Booster::sendDataToParent() { // Number of data items to be sent to // the parent (launcher) process const unsigned int NUM_DATA_ITEMS = 3; struct iovec iov[NUM_DATA_ITEMS]; struct msghdr msg; struct cmsghdr *cmsg; char buf[CMSG_SPACE(sizeof(int))]; // Signal the parent process that it can create a new // waiting booster process and close write end const char booster = boosterType(); iov[0].iov_base = const_cast<char *>(&booster); iov[0].iov_len = sizeof(char); // Send to the parent process pid of invoker for tracking pid_t pid = invokersPid(); iov[1].iov_base = &pid; iov[1].iov_len = sizeof(pid_t); // Send to the parent process booster respawn delay value int delay = m_appData->delay(); iov[2].iov_base = &delay; iov[2].iov_len = sizeof(int); msg.msg_iov = iov; msg.msg_iovlen = NUM_DATA_ITEMS; msg.msg_name = NULL; msg.msg_namelen = 0; // Set special control fields if exit status of the launched // application is needed. In this case we want to give the fd of the // invoker <-> booster socket connection to the parent process (launcher) // so that it can send the exit status back to invoker. It'd be impossible // from the booster process if exec() was used. if (m_connection->isReportAppExitStatusNeeded()) { // Send socket file descriptor to parent int fd = m_connection->getFd(); msg.msg_control = buf; msg.msg_controllen = sizeof(buf); cmsg = CMSG_FIRSTHDR(&msg); cmsg->cmsg_level = SOL_SOCKET; cmsg->cmsg_type = SCM_RIGHTS; cmsg->cmsg_len = CMSG_LEN(sizeof(int)); memcpy(CMSG_DATA(cmsg), &fd, sizeof(int)); } else { msg.msg_control = NULL; msg.msg_controllen = 0; } if (sendmsg(boosterLauncherSocket(), &msg, 0) < 0) { Logger::logError("Booster: Couldn't send data to launcher process\n"); } }
void Booster::initialize(int initialArgc, char ** initialArgv, int newBoosterLauncherSocket, int socketFd, SingleInstance * singleInstance, bool newBootMode) { m_bootMode = newBootMode; setBoosterLauncherSocket(newBoosterLauncherSocket); // Drop priority (nice = 10) pushPriority(10); // Preload stuff if (!m_bootMode) preload(); // Rename process to temporary booster process name std::string temporaryProcessName = "booster ["; temporaryProcessName += boosterType(); temporaryProcessName += "]"; const char * tempArgv[] = {temporaryProcessName.c_str()}; renameProcess(initialArgc, initialArgv, 1, tempArgv); // Restore priority popPriority(); while (true) { // Wait and read commands from the invoker Logger::logDebug("Booster: Wait for message from invoker"); if (!receiveDataFromInvoker(socketFd)) throw std::runtime_error("Booster: Couldn't read command\n"); // Run process as single instance if requested if (m_appData->singleInstance()) { // Check if instance is already running SingleInstancePluginEntry * pluginEntry = singleInstance->pluginEntry(); if (pluginEntry) { if (!pluginEntry->lockFunc(m_appData->appName().c_str())) { // Try to activate the window of the existing instance if (!pluginEntry->activateExistingInstanceFunc(m_appData->appName().c_str())) { Logger::logWarning("Booster: Can't activate existing instance of the application!"); m_connection->sendExitValue(EXIT_FAILURE); } else { m_connection->sendExitValue(EXIT_SUCCESS); } m_connection->close(); // invoker requested to start an application that is already running // booster is not needed this time, let's wait for the next connection from invoker continue; } // Close the single-instance plugin singleInstance->closePlugin(); } else { Logger::logWarning("Booster: Single-instance launch wanted, but single-instance plugin not loaded!"); } } //this instance of booster will be used to start application, exit from the loop break; } // Send parent process a message that it can create a new booster, // send pid of invoker, booster respawn value and invoker socket connection. sendDataToParent(); // Give the process the real application name now that it // has been read from invoker in receiveDataFromInvoker(). renameProcess(initialArgc, initialArgv, m_appData->argc(), m_appData->argv()); close(boosterLauncherSocket()); // close invoker socket connection m_connection->close(); // Don't care about fate of parent applauncherd process any more prctl(PR_SET_PDEATHSIG, 0); }