简体   繁体   中英

How can I make a linux background process (in c) that launches a Python script

I made a Linux background process (in c++) that monitors a directory and attempts to launch a Python script if a certain file appears in that directory. My issue is that the child process responsible for launching the Python script exits immediately after the execvp function is called and I can't understand why. All of the necessary files are under root's ownership. Here is my code if it helps. Thank you in advance for any pointers. I have marked the error in my code where the error occurs. I have also included the Python script to be called

#include <sys/types.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>

using namespace std;

char* arguments[3];
FILE* fd;
const char* logFilePath = "/home/BluetoothProject/Logs/fileMonitorLogs.txt";
char* rfcommPath = (char*)"/home/BluetoothProject/RFCOMMOut.py";
void logToFile(const char*);
void doWork();

void logToFile(const char* str) {
    fd = fopen(logFilePath, "a");
    fprintf(fd, "%s\n", str);
    fclose(fd);
}

int main() {
    arguments[0] = (char*)"python";
    arguments[1] = rfcommPath;
    arguments[2] = NULL;
    pid_t pid = fork();
    if(pid < 0) {
        printf("Fork failed");
        exit(1);
    } else if(pid > 0) {
        exit(EXIT_SUCCESS);
    }
    umask(0);
    pid_t sid = setsid();
    if(sid < 0) {
        logToFile("setsid() didn't work.");
        exit(1);
    }
    if ((chdir("/")) < 0) {
                logToFile("chdir() didn't work.");
                exit(EXIT_FAILURE);
        }
        close(STDIN_FILENO);
        close(STDOUT_FILENO);
        close(STDERR_FILENO);
    doWork();
}

void doWork() {
    pid_t pid = fork();
    if(pid < 0) {
        logToFile("doWork() fork didn't work.");
    } else if(pid > 0) {
        int status = 0;
        waitpid(pid, &status, 0);
        if(WEXITSTATUS(status) == 1) {
            logToFile("Child process exited with an error.");
        }
    } else {
        int error = execvp(arguments[0], arguments);   //Here is where the error is
        if(error == -1) {
            logToFile("execvp() failed.");
        }
        exit(1);
    }
}

Python script (AKA RFCOMMOut.py)

import RPi.GPIO as gpio
import serial
led_state = 0
led_pin = 11
gpio.setmode(gpio.BOARD)
gpio.setwarnings(False)
gpio.setup(led_pin, gpio.OUT)
try:
    ser = serial.Serial(port = '/dev/rfcomm0',
            baudrate = 9600,
            parity = serial.PARITY_NONE,
            stopbits = serial.STOPBITS_ONE,
            bytesize = serial.EIGHTBITS)
except IOException as e:
    logFile = open("/home/BluetoothProject/Logs/fileMonitorLogs.txt", "a")
        logFile.write("(First error handler) There was an exception:\n")
        logFile.write(str(e))
    logFile.write("\n")
        logFile.close()

#gpio.output

def process_input(input):
    global led_state
        if input == "I have been sent.\n":
                if led_state == 1:
            led_state = 0
            gpio.output(led_pin, led_state)
        else:
            led_state = 1
            gpio.output(led_pin, led_state)

while True:
    try:
        transmission = ser.readline()
        process_input(transmission)
    except IOError as e:
        logFile = open("/home/BluetoothProject/Logs/fileMonitorLogs.txt", "a")
        logFile.write("(second error handler) There was an exception:\n")
        logFile.write(str(e))
        logFile.write("\n")
        logFile.close()
        break
led_state = 0
gpio.output(led_pin, led_state)
gpio.cleanup()
print("End of program\n")

The question is a little unclear, so I'll try to take a few different educated guesses at what the problem is and address each one individually.

TL;DR: Remove close(STDOUT_FILENO) and close(STDERR_FILENO) to get more debugging information which will hopefully point you in the right direction.

execvp(3) is returning -1

According to the execvp(3) documentation, execvp(3) sets errno when it fails. In order to understand why it is failing, your program will need to output the value of errno somewhere; perhaps stdout, stderr, or your log file. A convenient way to do this is to use perror(3) . For example:

#include <stdio.h>
...
void doWork() {
  ...
  } else {
    int error = execvp(arguments[0], arguments);
    if(error == -1) {
      perror("execvp() failed");
    }
  }
  ...
}

Without knowing what that errno value is, it will be difficult to identify why execvp(3) is failing.

execvp(3) is succeeding, but my Python program doesn't appear run

execvp(3) succeeding means that the Python interpreter has successfully been invoked (assuming that there is no program in your PATH that is named "python", but is not actually a Python interpreter). If your program doesn't appear to be running, that means Python is having difficulty loading your program. To my knowledge, Python will always output relevant error messages in this situation to stderr; for example, if Python cannot find your program, it will output "No such file or directory" to stderr.

However, it looks like your C program is calling close(STDERR_FILENO) before calling doWork() . According to fork(2) , child processes inherit copies of their parent's set of open file descriptors. This means that calling close(STDERR_FILENO) before forking will result in the child process not having an open stderr file descriptor. If Python is having any errors executing your program, you'll never know, since Python is trying to notify you through a file descriptor that doesn't exist. If execvp(3) is succeeding and the Python program appears to not run at all, then I recommend you remove close(STDERR_FILENO) from your C program and run everything again. Without seeing the error message output by Python, it will be difficult to identify why it is failing to run the Python program.

As an aside, I recommend against explicitly closing stdin, stdout, and stderr. According to stdin(3) , the standard streams are closed by a call to exit(3) and by normal program termination.

execvp(3) is succeeding, my Python program is running, but my Python program exits before it does any useful work

In this case, I'm not sure what the problem might be, since I'm not very familiar with Raspberry Pi. But I think you'll have an easier time debugging if you don't close the standard streams before running the Python program.

Hope this helps.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM