简体   繁体   English

主进程-> pthread-> fork + execvp

[英]main process -> pthread -> fork + execvp

I am seeing a strange issue. 我看到一个奇怪的问题。

Sometimes when i run my program long enough i see that there are two copies of my program running. 有时,当我运行我的程序足够长的时间时,我看到我的程序有两个副本在运行。 The second is a child process of the first since i see that the parent PID of the second one is that of the first one. 第二个是第一个的子进程,因为我看到第二个的父PID是第一个的父进程。

I realized that i have a fork in my code and its only because of this that i can have two copies running -- i can otherwise never have two copies of my program running. 我意识到我的代码中有一个分支,唯一的原因是我可以运行两个副本–否则,我永远都不能运行程序的两个副本。

This happens very rarely but it does happen. 这种情况很少发生,但是确实发生。

The architecture is as follows: 架构如下:

The main program gets an event and spawns a pthread. 主程序获取一个事件并生成一个pthread。 In that thread i do some processing and based on some result i do a fork immediately followed by an execvp. 在该线程中,我进行了一些处理,并基于某些结果,立即执行了fork,然后执行execvp。

I realize that its not best to call a fork from a pthread but in my design the main process gets many events and the only way to parallely work on all those events was to use pthreads. 我意识到最好不要从pthread调用fork,但是在我的设计中,主进程会收到许多事件,并且并行处理所有这些事件的唯一方法是使用pthreads。 Each pthread does some processing and in certain cases it needs to call a different program (for which i use execvp). 每个pthread都会进行一些处理,在某些情况下,它需要调用其他程序(为此我使用execvp)。 Since i had to call a different program i had to use fork 由于我必须调用其他程序,因此不得不使用fork

I am wondering if because i am eventually calling a fork from a thread context is it possible that multiple threads parallely call fork + execvp and this "somehow" results in two copies being created. 我想知道是否因为我最终要从线程上下文中调用派生,是否可能多个线程并行调用派生+ execvp,而这种“某种程度上”会导致创建两个副本。

If this is indeed happening would it help if i protect the code that does fork+execvp with a mutex since that would result in only one thread calling the fork + execvp. 如果确实发生了这种情况,那么如果我使用互斥锁保护执行fork + execvp的代码,将会有所帮助,因为那样只会导致一个线程调用fork + execvp。

However, if i take a mutex before fork + excvp then i dont know when to release it. 但是,如果我在fork + excvp之前使用了互斥锁,那么我不知道何时释放它。

Any help here would be appreciated. 在这里的任何帮助,将不胜感激。

thread code that does fork + execvp -- in case you guys can spot an issue there: 进行fork + execvp的线程代码-如果你们在那里发现问题:

In main.c 在main.c中

    status = pthread_create(&worker_thread, tattr, 
                                 do_some_useful_work, some_pointer);

[clipped] [剪切]

    void *do_some_useful_work (void * arg)
    {
          /* Do some processing and fill pArguments array */

          child_pid = fork();

          if (child_pid == 0)
          {
              char *temp_log_file;

              temp_log_file = (void *) malloc (strlen(FORK_LOG_FILE_LOCATION) +
                                        strlen("/logfile.") + 8);

               sprintf (temp_log_file, "%s/logfile.%d%c", FORK_LOG_FILE_LOCATION, getpid(),'\0');

               /* Open log file */
               int log = creat(temp_log_file, 0777);
               /* Redirect stdout to log file */
               close(1);
               dup(log);
               /* Redirect stderr to log file */
               close(2);
               dup(log);

               syslog(LOG_ERR, "Opening up log file %s\n", temp_log_file);

               free (temp_log_file);

               close (server_sockets_that_parent_is_listening_on);

               execvp ("jazzy_program", pArguments); 

         }

         pthread_exit (NULL);

         return NULL;
    }

I looked through this code and i see no reason why i would do a fork and not do an execvp -- so the only scenario that comes to my mind is that multiple threads get executed and they all call fork + execvp. 我查看了这段代码,没有理由不执行fork而不执行execvp -因此,我想到的唯一情况是执行了多个线程,并且它们都调用了fork + execvp。 This sometimes causes two copies of my main program to run. 有时这会导致我的主程序运行两个副本。

In the case where execvp fails for any reason (perhaps too many processes, out of memory, etc.), you fail to handle the error; 如果execvp由于任何原因(可能进程过多,内存不足等)而失败,则您将无法处理该错误; instead the forked copy of the thread keeps running. 相反,线程的分支副本将继续运行。 Calling pthread_exit (or any non-async-signal-safe) function in this process has undefined behavior, so it might not exit properly but hang or do something unexpected. 在此过程中调用pthread_exit (或任何非异步信号安全的)函数具有未定义的行为,因此它可能无法正确退出,但会挂起或执行意外操作。 You should always check for exec failure and immediately _exit(1) or similar when this happens. 您应该始终检查exec失败,并在发生这种情况时立即检查_exit(1)或类似错误。 Also, while this probably isn't your problem, it's unsafe to call malloc after forking in a multithreaded process since it's non-async-signal-safe. 另外,虽然这可能不是您的问题,但是在多线程进程中派生后调用malloc是不安全的,因为它是非异步信号安全的。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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