Форк не загружает программу в execv

Программа ниже не загружает программу в дочерний процесс и не печатает "до" и "после". Однако ps aux показывает создание процессов (но без загрузки программы args0). Я использую ТРУБУ, определенную как socketpair. args0[] содержит имя исполняемой программы для дочерней программы, args1[] содержит имя дочерней программы. args2 и args3 являются предопределенными значениями, которые не изменяются и должны быть отправлены дочерним элементам в качестве аргументов. вы можете считать, что char args2[] = "10" -> пользовательский ввод (цифра) и преобразован в строку. Я просто не понимаю, почему хотя бы printf("до") не печатается. я читал о fflush и помещал \n в каждый printf, и я сделал. так что все в моей программе напечатано правильно до этого момента.

Буду очень признателен за ваши ответы.

char args2[];
char args3[];
//creating pipe
int forkk(pipes *myPipe, server_message *m, char args0[],char args1[]) {
pid_t cpid;

//pipe passed myPipe[i]
if (PIPE(myPipe->fd) == -1) {
    perror("pipe error\n");
    return -1;
}
 fork();
 cpid=getpid();
if (cpid == -1) {
    perror("fork error\n");
    return -1;
}
if (cpid) {
    close(myPipe->fd[1]);
    return 1;//closing one end of parent

} else {

    for (int i = 3; i <= myPipe->fd[0]; i++) {
        close(i);
    }

    dup2(myPipe->fd[1], 0); //redirecting stdin of child
    dup2(myPipe->fd[1], 1); //redirecting stdout of child
    close(myPipe->fd[1]);
    myPipe->cpid = cpid;
    char *newargs[3];
    newargs[0]=args1;
    newargs[1]=args2;
    newargs[2]=args3;
    printf("before\n");
    //fflush(stdout);
    execv(args0,newargs);
    printf("after execv\n");
    write(myPipe->fd[0], &m, sizeof(server_message));  //send the server_msg immediately (pass an array or msg)

}
    return 2;

}

void main(){
....
scanf("%d %d", &width, &height);
sprintf(args2,"%d",height); //converting into to string
sprintf(args3,"%d",width);
char *args0 = "./prey";
char *args1 = "prey";
int r= forkk(&myPipes[2], &msg, args0,args1);

}

Я не могу опубликовать весь код, так как он длинный и требует объяснения. Скорее всего, у меня проблема с назначением указателя, что я ошибочно считаю правильным способом. Большое спасибо за любую помощь

1 ответ

Решение

(спойлер: твой else филиал в вашем плохо названном forkk никогда не берется!)

Внимательно прочитайте документацию execv (3). Вы должны предоставить NULL прекращенный массив.

Функции execv(), execvp() и execvpe() предоставляют массив указателей на строки с нулевым символом в конце, которые представляют список аргументов, доступных для новой программы. Первый аргумент, по соглашению, должен указывать на имя файла, связанное с исполняемым файлом. Массив указателей должен заканчиваться нулевым указателем.

Так что вы должны хотя бы кодировать:

char *newargs[4];
newargs[0]=args1;
newargs[1]=args2;
newargs[2]=args3;
newargs[3] = NULL; // mandatory last NULL pointer
execv(args0,newargs);

Кстати, первый аргумент обычно должен быть именем программы. Итак, вы действительно хотите:

char *newargs[5];
newargs[0] = args0;
newargs[1]=args1;
newargs[2]=args2;
newargs[3]=args3;
newargs[4] = NULL; // mandatory last NULL pointer
execv(args0,newargs);

И в документации тоже сказано

Функции exec() возвращаются, только если произошла ошибка.

Так что в большинстве случаев нет смысла продолжать здесь, так как execv не вернется в случае успеха Однако вам нужно поймать неудачу. Я рекомендую после вашего execv

perror(arg0); // or perhaps perror("execv");
exit(EXIT_FAILURE);

Ваш write(myPipe->fd[0], &m, sizeof(server_message)); очень плохо пахнет. Я не вижу смысла делать это (только), когда execv терпит неудачу

Кстати, с помощью strace(1) вы, вероятно, поймали бы такую ​​ошибку (пропуская завершение NULL указатель для execv).

Наконец, вы всегда должны сохранять результат fork (2). Смотрите это. Так что замените:

 fork(); // WRONG
 cpid=getpid(); // always positive!

с cpid = fork();

Конечно, вам нужно разобраться с тремя случаями: cpid== -1 (что вы забыли обработать!), cpid== 0, cpid> 0,

Опять же, внимательно прочитайте getpid (2):

getpid () возвращает идентификатор процесса (PID) вызывающего процесса.

и о getpid & getppid):

Эти функции всегда успешны

Так getpid никогда не возвращает 0 (и именно поэтому ваш else филиал в вашем forkk плохо названная функция, содержащая execvp никогда не запускается). Смотрите также полномочия (7).

Ваш void main() тоже неправильно. main должен вернуть int, Вы обычно определяете это как int main(int argc, char**argv)...

PS. Возьмите за правило внимательно читать документацию по каждой функции, которую вы используете.

Ваш forkk очень плохо назван, слишком похож на очень важный fork название.

Другие вопросы по тегам