Esempio n. 1
0
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");
    }
}
Esempio n. 2
0
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);
}