mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-02-07 15:03:34 +00:00
Fix popen_test in MODE=dbg
ASAN and vfork() don't appear to play well together. Maybe in later versions of GCC it'll be better. But vfork() is flirting with danger after all and that probably doesn't make sense in ASAN mode anyway.
This commit is contained in:
parent
cef08d47b6
commit
fabf7f9f02
5 changed files with 35 additions and 14 deletions
|
@ -20,6 +20,11 @@
|
|||
#include "libc/macros.internal.h"
|
||||
.privileged
|
||||
|
||||
#ifdef __FSANITIZE_ADDRESS__
|
||||
vfork: jmp fork # TODO: asan and vfork don't mix?
|
||||
.endfn vfork,globl
|
||||
#else
|
||||
|
||||
// Forks process without copying page tables.
|
||||
//
|
||||
// This is the same as fork() except it's optimized for the case
|
||||
|
@ -75,3 +80,5 @@ vfork.bsd:
|
|||
jmp 0b
|
||||
.endfn vfork.bsd
|
||||
#endif /* BSD */
|
||||
|
||||
#endif /* __FSANITIZE_ADDRESS__ */
|
||||
|
|
|
@ -23,11 +23,11 @@
|
|||
* @return byte in range 0..255, or -1 w/ errno
|
||||
*/
|
||||
int fgetc(FILE *f) {
|
||||
unsigned char b;
|
||||
unsigned char b[1];
|
||||
if (f->beg < f->end) {
|
||||
return f->buf[f->beg++] & 0xff;
|
||||
} else {
|
||||
if (!fread(&b, 1, 1, f)) return -1;
|
||||
return b;
|
||||
if (!fread(b, 1, 1, f)) return -1;
|
||||
return b[0];
|
||||
}
|
||||
}
|
||||
|
|
|
@ -33,7 +33,7 @@
|
|||
*/
|
||||
FILE *popen(const char *cmdline, const char *mode) {
|
||||
FILE *f;
|
||||
int dir, flags, pipefds[2];
|
||||
int e, pid, dir, flags, pipefds[2];
|
||||
flags = fopenflags(mode);
|
||||
if ((flags & O_ACCMODE) == O_RDONLY) {
|
||||
dir = 0;
|
||||
|
@ -45,13 +45,28 @@ FILE *popen(const char *cmdline, const char *mode) {
|
|||
}
|
||||
if (pipe(pipefds) == -1) return NULL;
|
||||
fcntl(pipefds[dir], F_SETFD, FD_CLOEXEC);
|
||||
if (!(f = fdopen(pipefds[dir], mode))) abort();
|
||||
if ((f->pid = vfork()) == -1) abort();
|
||||
if (!f->pid) {
|
||||
dup2(pipefds[!dir], !dir);
|
||||
systemexec(cmdline);
|
||||
_exit(127);
|
||||
if ((f = fdopen(pipefds[dir], mode))) {
|
||||
switch ((pid = vfork())) {
|
||||
case 0:
|
||||
dup2(pipefds[!dir], !dir);
|
||||
systemexec(cmdline);
|
||||
_exit(127);
|
||||
default:
|
||||
f->pid = pid;
|
||||
close(pipefds[!dir]);
|
||||
return f;
|
||||
case -1:
|
||||
e = errno;
|
||||
fclose(f);
|
||||
close(pipefds[!dir]);
|
||||
errno = e;
|
||||
return NULL;
|
||||
}
|
||||
} else {
|
||||
e = errno;
|
||||
close(pipefds[0]);
|
||||
close(pipefds[1]);
|
||||
errno = e;
|
||||
return NULL;
|
||||
}
|
||||
close(pipefds[!dir]);
|
||||
return f;
|
||||
}
|
||||
|
|
|
@ -14,7 +14,7 @@ COSMOPOLITAN_C_START_
|
|||
|
||||
typedef struct FILE {
|
||||
uint8_t bufmode; /* 0x00 _IOFBF, etc. (ignored if fd=-1) */
|
||||
bool noclose; /* 0x01 for fake dup() */
|
||||
bool noclose; /* 0x01 for fake dup() todo delete! */
|
||||
uint32_t iomode; /* 0x04 O_RDONLY, etc. (ignored if fd=-1) */
|
||||
int32_t state; /* 0x08 0=OK, -1=EOF, >0=errno */
|
||||
int fd; /* 0x0c ≥0=fd, -1=closed|buffer */
|
||||
|
|
|
@ -23,7 +23,6 @@
|
|||
TEST(popen, test) {
|
||||
int ws;
|
||||
FILE *f;
|
||||
/* TODO(jart): look into popen() asan error */
|
||||
f = popen("echo hi", "r");
|
||||
ASSERT_NE(NULL, f);
|
||||
EXPECT_EQ('h', fgetc(f));
|
||||
|
|
Loading…
Reference in a new issue