0
0 комментариев

Есть две программы, общающиеся между собой по именованным каналам. Одна на C++, вторая на Python. Причём первая запускает вторую (стандартным способом, через fork + exec).

Участок коммуникации родительской программы (C++):

// ...
int pipeDescr;
std::string outputPipeName{"inputPipe"};
std::string inputPipeName{"outputPipe"};
char *message = new char[BUFSIZE];
// ...
while (true)
{
    int bytesNumber = 0;
    // ...
    if ((pipeDescr = open(outputPipeName.c_str(), O_WRONLY)) <= 0)
        break;
 
    bytesNumber = write(pipeDescr, message, strlen(message));
    if (bytesNumber <= 0)
        break;
 
    close(pipeDescr);
 
    message[0] = '\0';
    if ((pipeDescr = open(inputPipeName.c_str(), O_RDONLY)) <= 0)
        break;
 
    bytesNumber = read(pipeDescr, message, BUFSIZE);
    if (bytesNumber <= 0)
        break;
 
    close(pipeDescr);
    // ...
}

В отдельном потоке работает функция watchDog, которая несёт ответственность за работу дочернего приложения на Python.

void watchDog(int clientSocket, pid_t pid, bool &stopWatchDog)
{
    while (true)
    {
        // Дочерняя программа завершилась с ошибкой
        if (waitpid(pid, NULL, WNOHANG) != 0)
        {
            // ...
        }
 
        // Родительская программа закрывается
        mutexClosing.lock();
        if (closing)
        {
            mutexClosing.unlock();
            if (waitpid(pid, NULL, WNOHANG) == 0)
            {
                kill(pid, SIGTERM);
                waitpid(pid, NULL, 0);
            }
            break;
        }
        mutexClosing.unlock();
 
        // Программное отключение WatchDog-а
        mutexWatchDog.lock();
        if (stopWatchDog)
        {
            if (waitpid(pid, NULL, WNOHANG) == 0)
            {
                kill(pid, SIGTERM);
                waitpid(pid, NULL, 0);
            }
            mutexWatchDog.unlock();
            break;
        }
        mutexWatchDog.unlock();
    }
}

При этом есть три исхода:

  • падение дочерней программы

  • завершение родительской программы

  • завершение дочерней программы без завершения родительской

В последних двух вариантах необходимо плавно завершить дочернюю программу, поэтому, я отправляю ей сигнал SIGTERM и ожидаю завершения.

Участок коммуникации дочерней программы (Python):

def sigterm_handler(signal, frame):
    print('\nGot sigterm!\n')
    sys.exit(0)
 
def main():
    input_pipe_name = "inputPipe"
    output_pipe_name = "outputPipe"
    # ...
    signal.signal(signal.SIGTERM, sigterm_handler)
    # ...
    while True:
        pipe_descr = os.open(input_pipe_name, os.O_RDONLY)
        request = os.read(pipe_descr, 10000)
        os.close(pipe_descr)
 
        reply = work_func(request)
 
        pipe_descr = os.open(output_pipe_name, os.O_WRONLY)
        os.write(pipe_descr, bytes(reply, 'UTF-8'))
        os.close(pipe_descr)

В код я добавил обработку сигнала SIGTERM. Однако, при передаче этого сигнала, функция sigterm_handler не вызывается.

Но! Если написать что-то типа этого:

def main():
    signal.signal(signal.SIGTERM, sigterm_handler)
 
    while True:
        print('waiting...')
        time.sleep(2)

То функция вызовется.

Подскажите, как решить данную проблему!


Добавить комментарий