Browse Source

[multiple] _WIN32 fdevent_pipe_cloexec()

Note: Under _WIN32, serious limitation in Windows APIs:
  select() and WSAPoll() operate only on sockets (not pipes)
  (directly affects mod_cgi; not currently handled)
Glenn Strauss 11 months ago
parent
commit
3d366dfd80
  1. 3
      src/configfile.c
  2. 29
      src/fdevent.c
  3. 1
      src/fdevent.h
  4. 4
      src/fdlog_maint.c
  5. 24
      src/mod_cgi.c
  6. 6
      src/mod_rrdtool.c
  7. 3
      src/server.c

3
src/configfile.c

@ -2240,7 +2240,7 @@ int config_parse_cmd(server *srv, config_t *context, const char *cmd) {
}
}
if (pipe(fds)) {
if (fdevent_pipe_cloexec(fds, 65536)) {
log_perror(srv->errh, __FILE__, __LINE__, "pipe()");
ret = -1;
}
@ -2253,7 +2253,6 @@ int config_parse_cmd(server *srv, config_t *context, const char *cmd) {
*(const char **)&args[2] = cmd;
args[3] = NULL;
fdevent_setfd_cloexec(fds[0]);
pid = fdevent_fork_execve(args[0], args, NULL, -1, fds[1], -1, -1);
if (-1 == pid) {
log_perror(srv->errh, __FILE__, __LINE__, "fork/exec(%s)", cmd);

29
src/fdevent.c

@ -609,6 +609,35 @@ int fdevent_open_dirname(char *path, int symlinks) {
}
#ifdef _WIN32
#include <stdio.h>
#endif
int fdevent_pipe_cloexec (int * const fds, const unsigned int bufsz_hint) {
#ifdef _WIN32
return _pipe(fds, bufsz_hint, _O_BINARY | _O_NOINHERIT);
#else
#ifdef HAVE_PIPE2
if (0 != pipe2(fds, O_CLOEXEC))
#endif
{
if (0 != pipe(fds)
#ifdef FD_CLOEXEC
|| 0 != fcntl(fds[0], F_SETFD, FD_CLOEXEC)
|| 0 != fcntl(fds[1], F_SETFD, FD_CLOEXEC)
#endif
)
return -1;
}
#ifdef F_SETPIPE_SZ
if (bufsz_hint > 65536)
fcntl(fds[1], F_SETPIPE_SZ, bufsz_hint);
#endif
return 0;
#endif
}
int fdevent_mkostemp(char *path, int flags) {
#if defined(HAVE_MKOSTEMP)
return mkostemp(path, O_CLOEXEC | flags);

1
src/fdevent.h

@ -87,6 +87,7 @@ int fdevent_socket_cloexec(int domain, int type, int protocol);
int fdevent_socket_nb_cloexec(int domain, int type, int protocol);
int fdevent_dup_cloexec(int fd);
int fdevent_open_cloexec(const char *pathname, int symlinks, int flags, mode_t mode);
int fdevent_pipe_cloexec (int *fds, unsigned int bufsz_hint);
int fdevent_mkostemp(char *path, int flags);
int fdevent_rename(const char *oldpath, const char *newpath);

4
src/fdlog_maint.c

@ -190,10 +190,8 @@ fdlog_pipe_open (const char * const fn)
}
int fds[2];
if (pipe(fds))
if (fdevent_pipe_cloexec(fds, 65536))
return NULL;
fdevent_setfd_cloexec(fds[0]);
fdevent_setfd_cloexec(fds[1]);
pid_t pid = fdlog_pipe_spawn(fn, fds[0]);
if (pid > 0) {

24
src/mod_cgi.c

@ -27,19 +27,6 @@
#include <fcntl.h>
#include <signal.h>
static int pipe_cloexec(int pipefd[2]) {
#ifdef HAVE_PIPE2
if (0 == pipe2(pipefd, O_CLOEXEC)) return 0;
#endif
return 0 == pipe(pipefd)
#ifdef FD_CLOEXEC
&& 0 == fcntl(pipefd[0], F_SETFD, FD_CLOEXEC)
&& 0 == fcntl(pipefd[1], F_SETFD, FD_CLOEXEC)
#endif
? 0
: -1;
}
typedef struct {
uintptr_t *offsets;
size_t osize;
@ -665,8 +652,6 @@ static int cgi_write_request(handler_ctx *hctx, int fd) {
chunkqueue_remove_finished_chunks(cq); /* unnecessary? */
/* old comment: windows doesn't support select() on pipes - wouldn't be easy to fix for all platforms.
* solution: if this is still a problem on windows, then substitute
* socketpair() for pipe() and closesocket() for close() on windows.
*/
for (c = cq->first; c; c = cq->first) {
@ -791,11 +776,16 @@ static int cgi_create_env(request_st * const r, plugin_data * const p, handler_c
}
#endif
if (-1 == to_cgi_fds[0] && pipe_cloexec(to_cgi_fds)) {
unsigned int bufsz_hint = 16384;
#ifdef _WIN32
if (r->reqbody_length <= 1048576)
bufsz_hint = (unsigned int)r->reqbody_length;
#endif
if (-1 == to_cgi_fds[0] && fdevent_pipe_cloexec(to_cgi_fds, bufsz_hint)) {
log_perror(r->conf.errh, __FILE__, __LINE__, "pipe failed");
return -1;
}
if (pipe_cloexec(from_cgi_fds)) {
if (fdevent_pipe_cloexec(from_cgi_fds, bufsz_hint)) {
if (0 == r->reqbody_length) {
close(to_cgi_fds[0]);
}

6
src/mod_rrdtool.c

@ -86,18 +86,16 @@ static int mod_rrd_create_pipe(server *srv, plugin_data *p) {
* If pipes were to be shared, then existing pipes would need to be
* reused here, if they already exist (not -1), and after flushing
* existing contents (read and discard from read-end of pipes). */
if (pipe(to_rrdtool_fds)) {
if (fdevent_pipe_cloexec(to_rrdtool_fds, 4096)) {
log_perror(srv->errh, __FILE__, __LINE__, "pipe()");
return 0;
}
if (pipe(from_rrdtool_fds)) {
if (fdevent_pipe_cloexec(from_rrdtool_fds, 4096)) {
log_perror(srv->errh, __FILE__, __LINE__, "pipe()");
close(to_rrdtool_fds[0]);
close(to_rrdtool_fds[1]);
return 0;
}
fdevent_setfd_cloexec(to_rrdtool_fds[1]);
fdevent_setfd_cloexec(from_rrdtool_fds[0]);
const char * const path_rrdtool_bin = p->path_rrdtool_bin
? p->path_rrdtool_bin->ptr
: "/usr/bin/rrdtool";

3
src/server.c

@ -197,7 +197,7 @@ static int daemonize(void) {
signal(SIGTSTP, SIG_IGN);
#endif
if (pipe(pipefd) < 0) exit(-1);
if (fdevent_pipe_cloexec(pipefd, 64) < 0) exit(-1);
if (0 > (pid = fork())) exit(-1);
@ -231,7 +231,6 @@ static int daemonize(void) {
if (0 != chdir("/")) exit(0);
fdevent_setfd_cloexec(pipefd[1]);
return pipefd[1];
}
#endif

Loading…
Cancel
Save