2015-09-25 2 views
0

Я столкнулся с сценарием, который мне бы хотелось помочь. Ниже приведен пример кода.Записанный процесс записи в закрытый файловый дескриптор stderr

fclose(stdin); 
fclose(stdout); 
fclose(stderr); 
int sockets[2]; 
assert(socketpair(AF_UNIX, SOCK_STREAM, 0, sockets) == 0); 
int socketA = sockets[0]; 
int socketB = sockets[1]; 
assert(socketpair(AF_UNIX, SOCK_STREAM, 0, sockets) == 0); 
int socketC = sockets[0]; 
int socketD = sockets[1]; 
assert(socketA == 0); 
assert(socketB == 1); 
assert(socketC == 2); 
assert(socketD == 3); 
unblock_socket(socketA); 
unblock_socket(socketB); 
unblock_socket(socketC); 
unblock_socket(socketD); 
unsigned char buffer = 0; 
assert(::recv(socketA, &buffer, sizeof(buffer), 0) == -1); 
assert(::recv(socketC, &buffer, sizeof(buffer), 0) == -1); 
assert(::recv(socketB, &buffer, sizeof(buffer), 0) == -1); 
assert(::recv(socketD, &buffer, sizeof(buffer), 0) == -1); 
pid_t pid = fork(); 
if (pid == -1) 
    assertfalse; 
else if (pid > 0) 
{ 
    int status = 0; 
    waitpid(pid, &status, 0); 
} 
else 
{ 
    assert(execv("/usr/sbin/chown", nullptr) == 0) // Prints "usage: chown [-fhv] [-R [-H | -L | -P]]..." to stderr 
    _exit(EXIT_FAILURE); 
} 
assert(::recv(socketA, &buffer, sizeof(buffer), 0) == -1); 
assert(::recv(socketC, &buffer, sizeof(buffer), 0) == -1); 
assert(::recv(socketB, &buffer, sizeof(buffer), 0) == -1); 
assert(::recv(socketD, &buffer, sizeof(buffer), 0) == -1); // Assertion failed!. Reading from socket D we see "usage: chown [-fhv] [-R [-H | -L | -P]]..." 

Я закрыл Stderr (файловый дескриптор 2), а затем открыл разъем C, который занимает уже имеющийся дескриптор файла 2. Однако Чаун все еще, казалось бы, умудряется писать свой вывод ошибки в файл с дескриптором 2. Если Чаун не понимают STDERR был закрыт и файловый дескриптор 2 переопределен и поэтому не записывается в него?

Спасибо

ответ

0

Выполняется точно так, как должно.

Вы закрываете stderr, затем вызываете socketpair(). SocketC == 2 (т. Е. Теперь stderr).

chown() наследует эти файловые дескрипторы, поэтому при записи в stderr он действительно записывает SocketC, который родитель читает из SocketD.

+0

Как плохая практика закрывать stderr? Потому что, если я закрываю stderr, а затем его файловый дескриптор повторно используется (например, для сокета, как в этом случае), то сторонний код может записать в этот сокет в любой точке? Благодаря! – inhwank

0

Решено - я должен был перенаправить stdin/stdout/stderr в/dev/null, так что дескрипторы файла 0-2 не переназначаются. Это приложение-демон.

Однако я все еще нахожу это странным, Чаун печатает в файл с дескриптором 2. Мне кажется, Чаун печатает с помощью

dprintf(STDOUT_FILEERR, "usage: chown [-fhv] [-R [-H | -L | -P]]..."); 

или, возможно,

const char error[] = "usage: chown [-fhv] [-R [-H | -L | -P]]..."; 
write(STDOUT_FILENO, error, sizeof(error) - 1); 

вместо

fprintf(stderr, "usage: chown [-fhv] [-R [-H | -L | -P]]..."); 

или что-то подобное ... так как в первом примере dprintf записывает в socketC (дескриптор файла 2), который вызывает p roblems, но во втором примере fprintf реализует объект stderr FILE * закрыт и не выполняет запись.

Любое дальнейшее понимание было бы высоко оценено.

Смежные вопросы