Skip to content
This repository has been archived by the owner on Apr 22, 2023. It is now read-only.

Commit

Permalink
Browse files Browse the repository at this point in the history
deps: upgrade libuv to c8c9fe1
  • Loading branch information
bnoordhuis committed Jun 5, 2012
1 parent 27061cc commit 0a2076b
Show file tree
Hide file tree
Showing 45 changed files with 1,564 additions and 679 deletions.
3 changes: 3 additions & 0 deletions deps/uv/include/uv-private/uv-unix.h
Expand Up @@ -35,6 +35,8 @@
#include <netdb.h>
#include <pwd.h>
#include <termios.h>

#include <semaphore.h>
#include <pthread.h>

#if __sun
Expand All @@ -58,6 +60,7 @@ typedef pthread_once_t uv_once_t;
typedef pthread_t uv_thread_t;
typedef pthread_mutex_t uv_mutex_t;
typedef pthread_rwlock_t uv_rwlock_t;
typedef sem_t uv_sem_t;

/* Platform-specific definitions for uv_spawn support. */
typedef gid_t uv_gid_t;
Expand Down
2 changes: 2 additions & 0 deletions deps/uv/include/uv-private/uv-win.h
Expand Up @@ -169,6 +169,8 @@ typedef SOCKET uv_os_sock_t;

typedef HANDLE uv_thread_t;

typedef HANDLE uv_sem_t;

typedef CRITICAL_SECTION uv_mutex_t;

typedef union {
Expand Down
11 changes: 10 additions & 1 deletion deps/uv/include/uv.h
Expand Up @@ -432,7 +432,7 @@ UV_EXTERN void uv_close(uv_handle_t* handle, uv_close_cb close_cb);
* base and len members of the uv_buf_t struct. The user is responsible for
* freeing base after the uv_buf_t is done. Return struct passed by value.
*/
UV_EXTERN uv_buf_t uv_buf_init(char* base, size_t len);
UV_EXTERN uv_buf_t uv_buf_init(char* base, unsigned int len);


/*
Expand Down Expand Up @@ -1624,6 +1624,15 @@ UV_EXTERN void uv_rwlock_wrlock(uv_rwlock_t* rwlock);
UV_EXTERN int uv_rwlock_trywrlock(uv_rwlock_t* rwlock);
UV_EXTERN void uv_rwlock_wrunlock(uv_rwlock_t* rwlock);

/*
* Same goes for the semaphore functions.
*/
UV_EXTERN int uv_sem_init(uv_sem_t* sem, unsigned int value);
UV_EXTERN void uv_sem_destroy(uv_sem_t* sem);
UV_EXTERN void uv_sem_post(uv_sem_t* sem);
UV_EXTERN void uv_sem_wait(uv_sem_t* sem);
UV_EXTERN int uv_sem_trywait(uv_sem_t* sem);

/* Runs a function once and only once. Concurrent calls to uv_once() with the
* same guard will block all callers except one (it's unspecified which one).
* The guard should be initialized statically with the UV_ONCE_INIT macro.
Expand Down
7 changes: 7 additions & 0 deletions deps/uv/src/unix/core.c
Expand Up @@ -604,6 +604,13 @@ static void uv__io_rw(struct ev_loop* ev, ev_io* w, int events) {
uv__io_t* handle = container_of(w, uv__io_t, io_watcher);
u.data = handle->io_watcher.data;
u.cb(loop, handle, events & (EV_READ|EV_WRITE|EV_ERROR));

/* The callback may have closed all active handles. Stop libev from entering
* the epoll_wait/kevent/port_getn/etc. syscall if that's the case, it would
* hang indefinitely.
*/
if (loop->active_handles == 0)
ev_break(loop->ev, EVBREAK_ONE);
}


Expand Down
113 changes: 68 additions & 45 deletions deps/uv/src/unix/process.c
Expand Up @@ -28,6 +28,7 @@
#include <poll.h>
#include <unistd.h>
#include <stdio.h>
#include <fcntl.h>

#ifdef __APPLE__
# include <TargetConditionals.h>
Expand Down Expand Up @@ -217,6 +218,68 @@ static void uv__process_close_stream(uv_stdio_container_t* container) {
uv__stream_close((uv_stream_t*)container->data.stream);
}


static void uv__process_child_init(uv_process_options_t options,
int stdio_count,
int* pipes) {
int i;

if (options.flags & UV_PROCESS_DETACHED) {
setsid();
}

/* Dup fds */
for (i = 0; i < stdio_count; i++) {
/*
* stdin has swapped ends of pipe
* (it's the only one readable stream)
*/
int close_fd = i == 0 ? pipes[i * 2 + 1] : pipes[i * 2];
int use_fd = i == 0 ? pipes[i * 2] : pipes[i * 2 + 1];

if (use_fd >= 0) {
close(close_fd);
} else if (i < 3) {
/* `/dev/null` stdin, stdout, stderr even if they've flag UV_IGNORE */
use_fd = open("/dev/null", i == 0 ? O_RDONLY : O_RDWR);

if (use_fd < 0) {
perror("failed to open stdio");
_exit(127);
}
} else {
continue;
}

if (i != use_fd) {
dup2(use_fd, i);
close(use_fd);
}
}

if (options.cwd && chdir(options.cwd)) {
perror("chdir()");
_exit(127);
}

if ((options.flags & UV_PROCESS_SETGID) && setgid(options.gid)) {
perror("setgid()");
_exit(127);
}

if ((options.flags & UV_PROCESS_SETUID) && setuid(options.uid)) {
perror("setuid()");
_exit(127);
}

environ = options.env;

execvp(options.file, options.args);
perror("execvp()");
_exit(127);
}


#ifndef SPAWN_WAIT_EXEC
# define SPAWN_WAIT_EXEC 1
#endif
Expand All @@ -229,7 +292,8 @@ int uv_spawn(uv_loop_t* loop, uv_process_t* process,
*/
char** save_our_env = environ;

int* pipes = malloc(2 * options.stdio_count * sizeof(int));
int stdio_count = options.stdio_count < 3 ? 3 : options.stdio_count;
int* pipes = malloc(2 * stdio_count * sizeof(int));

#if SPAWN_WAIT_EXEC
int signal_pipe[2] = { -1, -1 };
Expand Down Expand Up @@ -258,7 +322,7 @@ int uv_spawn(uv_loop_t* loop, uv_process_t* process,
process->exit_cb = options.exit_cb;

/* Init pipe pairs */
for (i = 0; i < options.stdio_count; i++) {
for (i = 0; i < stdio_count; i++) {
pipes[i * 2] = -1;
pipes[i * 2 + 1] = -1;
}
Expand Down Expand Up @@ -308,49 +372,8 @@ int uv_spawn(uv_loop_t* loop, uv_process_t* process,

if (pid == 0) {
/* Child */
if (options.flags & UV_PROCESS_DETACHED) {
setsid();
}

/* Dup fds */
for (i = 0; i < options.stdio_count; i++) {
/*
* stdin has swapped ends of pipe
* (it's the only one readable stream)
*/
int close_fd = i == 0 ? pipes[i * 2 + 1] : pipes[i * 2];
int use_fd = i == 0 ? pipes[i * 2] : pipes[i * 2 + 1];

if (use_fd >= 0) {
close(close_fd);
dup2(use_fd, i);
} else {
/* Reset flags that might be set by Node */
uv__cloexec(i, 0);
uv__nonblock(i, 0);
}
}
uv__process_child_init(options, stdio_count, pipes);

if (options.cwd && chdir(options.cwd)) {
perror("chdir()");
_exit(127);
}

if ((options.flags & UV_PROCESS_SETGID) && setgid(options.gid)) {
perror("setgid()");
_exit(127);
}

if ((options.flags & UV_PROCESS_SETUID) && setuid(options.uid)) {
perror("setuid()");
_exit(127);
}

environ = options.env;

execvp(options.file, options.args);
perror("execvp()");
_exit(127);
/* Execution never reaches here. */
}

Expand Down Expand Up @@ -399,7 +422,7 @@ int uv_spawn(uv_loop_t* loop, uv_process_t* process,
error:
uv__set_sys_error(process->loop, errno);

for (i = 0; i < options.stdio_count; i++) {
for (i = 0; i < stdio_count; i++) {
close(pipes[i * 2]);
close(pipes[i * 2 + 1]);
}
Expand Down
35 changes: 18 additions & 17 deletions deps/uv/src/unix/stream.c
Expand Up @@ -561,12 +561,19 @@ static void uv__read(uv_stream_t* stream) {
struct msghdr msg;
struct cmsghdr* cmsg;
char cmsg_space[64];
int count;

/* Prevent loop starvation when the data comes in as fast as (or faster than)
* we can read it. XXX Need to rearm fd if we switch to edge-triggered I/O.
*/
count = 32;

/* XXX: Maybe instead of having UV_STREAM_READING we just test if
* tcp->read_cb is NULL or not?
*/
while ((stream->read_cb || stream->read2_cb) &&
stream->flags & UV_STREAM_READING) {
while ((stream->read_cb || stream->read2_cb)
&& (stream->flags & UV_STREAM_READING)
&& (count-- > 0)) {
assert(stream->alloc_cb);
buf = stream->alloc_cb((uv_handle_t*)stream, 64 * 1024);

Expand Down Expand Up @@ -890,42 +897,36 @@ int uv_write2(uv_write_t* req, uv_stream_t* stream, uv_buf_t bufs[], int bufcnt,
req->send_handle = send_handle;
ngx_queue_init(&req->queue);

if (bufcnt <= UV_REQ_BUFSML_SIZE) {
if (bufcnt <= UV_REQ_BUFSML_SIZE)
req->bufs = req->bufsml;
}
else {
else
req->bufs = malloc(sizeof(uv_buf_t) * bufcnt);
}

memcpy(req->bufs, bufs, bufcnt * sizeof(uv_buf_t));
req->bufcnt = bufcnt;

/*
* fprintf(stderr, "cnt: %d bufs: %p bufsml: %p\n", bufcnt, req->bufs, req->bufsml);
*/

req->write_index = 0;
stream->write_queue_size += uv__buf_count(bufs, bufcnt);

/* Append the request to write_queue. */
ngx_queue_insert_tail(&stream->write_queue, &req->queue);

assert(!ngx_queue_empty(&stream->write_queue));

/* If the queue was empty when this function began, we should attempt to
* do the write immediately. Otherwise start the write_watcher and wait
* for the fd to become writable.
*/
if (empty_queue) {
if (stream->connect_req) {
/* Still connecting, do nothing. */
}
else if (empty_queue) {
uv__write(stream);
} else {
}
else {
/*
* blocking streams should never have anything in the queue.
* if this assert fires then somehow the blocking stream isn't being
* sufficently flushed in uv__write.
* sufficiently flushed in uv__write.
*/
assert(!(stream->flags & UV_STREAM_BLOCKING));

uv__io_start(stream->loop, &stream->write_watcher);
}

Expand Down

0 comments on commit 0a2076b

Please sign in to comment.