【发布时间】:2019-09-18 13:12:02
【问题描述】:
我有一个用于 C 的插入器库。无法插入 vfork(),因为 vfork()(插入函数)在调用真正的 vfork() 后无法返回调用函数。但我插入_exit() 因为我需要知道该过程何时结束。当然,我正在插入exec*() 函数。我的问题是,当插入_exit() 时,当_exit() 被正常进程调用但不是当进程是受限制的vfork()'ed 进程时,我想做某些事情。
如何在 C 程序中判断我的进程何时是 vfork()'ed 进程以及何时我无权访问由 vfork() 返回的进程 ID?
转接器库:
/* COMPILE: gcc -shared -ldl -fPIC -o libso_interposer.so so_interposer.c -std=c99 */
/* RUN: LD_PRELOAD=./libso_interposer.so so_interposer_test */
#define _GNU_SOURCE
#include <stdio.h>
#include <dlfcn.h>
#include <unistd.h>
static void (*_exit_R)(int) = (void *) 0;
static pid_t (*fork_R)(void) = (void *) 0;
static void teardown_interposer() {
fprintf(stderr, "Destructing so_interposer.\n");
/* Concurrency protected code to be executed only once
* when the process finishes! */
/* Must not be executed if/when vfork() process finishes. */
}
pid_t fork(void) {
*(pid_t **) (&fork_R) = dlsym(RTLD_NEXT, "fork");
/* Code to prepare for a new process.
* More preparation in exec* interposing functions.*/
pid_t pid = fork_R();
return pid;
}
__attribute__((noreturn)) void _exit(int status) {
*(void **) (&_exit_R) = dlsym(RTLD_NEXT, "_exit");
fprintf(stderr, "Process '%lld' called _exit(%i).\n", (signed long long int) getpid(), status);
teardown_interposer();
_exit_R(status);
}
测试二进制文件:
/* COMPILE: gcc -std=c99 -D FORK=vfork -o so_interposer_test so_interposer_test.c */
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#if !defined(FORK)
#error "Define FORK: 'fork' or 'vfork'!"
#endif
int main(void) {
pid_t pid = FORK();
if(pid == 0) {
_exit(EXIT_SUCCESS);
} else if(pid > 0) {
_exit(EXIT_SUCCESS);
}
return EXIT_SUCCESS;
}
【问题讨论】:
-
“
vfork()无法返回调用函数”是什么意思?当然vfork返回。也许您正在考虑exec系列函数? -
我不确定你到底想要什么,但
vfork()会为子进程返回 0,就像fork()一样。 -
为什么你的函数不能返回?你真的在做什么?你能创建一个minimal reproducible example 给我们看吗?
-
@Someprogrammerdude 我有同样的问题,但the
vfork()man page 说“孩子不能从当前函数返回”。所以我认为这里的问题是关于如何在子进程中处理这个问题(尽管它当然需要澄清)。 -
自己的函数是不是要转发到真实的
vfork()?你能不能只转发到fork()或者比真正的vfork()限制更少的东西?