Alien-uv

 view release on metacpan or  search on metacpan

libuv/CONTRIBUTING.md  view on Meta::CPAN

  the reader doesn't have to make guesses. Make sure that the purpose and inner
  logic are either obvious to a reasonably skilled professional, or add a
  comment that explains it.


### COMMIT

Make sure git knows your name and email address:

```
$ git config --global user.name "J. Random User"
$ git config --global user.email "j.random.user@example.com"
```

Writing good commit logs is important.  A commit log should describe what
changed and why.  Follow these guidelines when writing one:

1. The first line should be 50 characters or less and contain a short
   description of the change prefixed with the name of the changed
   subsystem (e.g. "net: add localAddress and localPort to Socket").
2. Keep the second line blank.
3. Wrap all other lines at 72 columns.

libuv/ChangeLog  view on Meta::CPAN

* linux: increase thread stack size with musl libc (Ben Noordhuis)

* netbsd: correct uv_exepath() on NetBSD (Kamil Rytarowski)

* test: clean up semaphore after use (jBarz)

* win,build: bump vswhere_usability_wrapper to 2.0.0 (Refael Ackermann)

* win: let UV_PROCESS_WINDOWS_HIDE hide consoles (cjihrig)

* zos: lock protect global epoll list in epoll_ctl (jBarz)

* zos: change platform name to match python (jBarz)

* android: fix getifaddrs() (Zheng, Lei)

* netbsd: implement uv__tty_is_slave() (Kamil Rytarowski)

* zos: fix readlink for mounts with system variables (jBarz)

* test: sort the tests alphabetically (Sakthipriyan Vairamani)

libuv/ChangeLog  view on Meta::CPAN

* win: fix winapi function pointer typedef syntax (Brad King)

* test: fix tcp_close_while_connecting CI failures (Ben Noordhuis)

* test: make threadpool_cancel_single deterministic (Ben Noordhuis)

* test: make threadpool saturation reliable (Ben Noordhuis)

* unix: don't malloc in uv_thread_create() (Ben Noordhuis)

* unix: don't include CoreServices globally on macOS (Brad King)

* unix,win: add uv_translate_sys_error() public API (Philippe Laferriere)

* win: remove unused static variables (Ben Noordhuis)

* win: silence -Wmaybe-uninitialized warning (Ben Noordhuis)

* signal: replace pthread_once with uv_once (Santiago Gimeno)

* test: fix sign-compare warning (Will Speak)

libuv/README.md  view on Meta::CPAN

* One of:
  * [Visual C++ Build Tools][]
  * [Visual Studio 2015 Update 3][], all editions
    including the Community edition (remember to select
    "Common Tools for Visual C++ 2015" feature during installation).
  * [Visual Studio 2017][], any edition (including the Build Tools SKU).
    **Required Components:** "MSbuild", "VC++ 2017 v141 toolset" and one of the
    Windows SDKs (10 or 8.1).
* Basic Unix tools required for some tests,
  [Git for Windows][] includes Git Bash
  and tools which can be included in the global `PATH`.

To build, launch a git shell (e.g. Cmd or PowerShell), run `vcbuild.bat`
(to build with VS2017 you need to explicitly add a `vs2017` argument),
which will checkout the GYP code into `build/gyp`, generate `uv.sln`
as well as the necesery related project files, and start building.

```console
> vcbuild
```

libuv/appveyor.yml  view on Meta::CPAN

version: v1.18.0.build{build}

init:
  - git config --global core.autocrlf true

install:
  - cinst -y nsis

matrix:
  fast_finish: true
  allow_failures:
    - platform: x86
      configuration: Release
    - platform: x64

libuv/docs/code/uvwget/main.c  view on Meta::CPAN


    return 0;
}

int main(int argc, char **argv) {
    loop = uv_default_loop();

    if (argc <= 1)
        return 0;

    if (curl_global_init(CURL_GLOBAL_ALL)) {
        fprintf(stderr, "Could not init cURL\n");
        return 1;
    }

    uv_timer_init(loop, &timeout);

    curl_handle = curl_multi_init();
    curl_multi_setopt(curl_handle, CURLMOPT_SOCKETFUNCTION, handle_socket);
    curl_multi_setopt(curl_handle, CURLMOPT_TIMERFUNCTION, start_timeout);

libuv/docs/src/design.rst  view on Meta::CPAN


File I/O
^^^^^^^^

Unlike network I/O, there are no platform-specific file I/O primitives libuv could rely on,
so the current approach is to run blocking file I/O operations in a thread pool.

For a thorough explanation of the cross-platform file I/O landscape, checkout
`this post <http://blog.libtorrent.org/2012/10/asynchronous-disk-io/>`_.

libuv currently uses a global thread pool on which all loops can queue work. 3 types of
operations are currently run on this pool:

    * File system operations
    * DNS functions (getaddrinfo and getnameinfo)
    * User specified code via :c:func:`uv_queue_work`

.. warning::
    See the :c:ref:`threadpool` section for more details, but keep in mind the thread pool size
    is quite limited.

libuv/docs/src/guide/processes.rst  view on Meta::CPAN

exits. This is achieved using ``uv_spawn``.

.. rubric:: spawn/main.c
.. literalinclude:: ../../code/spawn/main.c
    :linenos:
    :lines: 6-8,15-
    :emphasize-lines: 11,13-17

.. NOTE::

    ``options`` is implicitly initialized with zeros since it is a global
    variable.  If you change ``options`` to a local variable, remember to
    initialize it to null out all unused fields::

        uv_process_options_t options = {0};

The ``uv_process_t`` struct only acts as the handle, all options are set via
``uv_process_options_t``. To simply launch a process, you need to set only the
``file`` and ``args`` fields. ``file`` is the program to execute. Since
``uv_spawn`` uses execvp_ internally, there is no need to supply the full
path. Finally as per underlying conventions, **the arguments array has to be

libuv/docs/src/loop.rst  view on Meta::CPAN

    Releases all internal loop resources. Call this function only when the loop
    has finished executing and all open handles and requests have been closed,
    or it will return UV_EBUSY. After this function returns, the user can free
    the memory allocated for the loop.

.. c:function:: uv_loop_t* uv_default_loop(void)

    Returns the initialized default loop. It may return NULL in case of
    allocation failure.

    This function is just a convenient way for having a global loop throughout
    an application, the default loop is in no way different than the ones
    initialized with :c:func:`uv_loop_init`. As such, the default loop can (and
    should) be closed with :c:func:`uv_loop_close` so the resources associated
    with it are freed.

    .. warning::
        This function is not thread safe.

.. c:function:: int uv_run(uv_loop_t* loop, uv_run_mode mode)

libuv/docs/src/threadpool.rst  view on Meta::CPAN

===========================

libuv provides a threadpool which can be used to run user code and get notified
in the loop thread. This thread pool is internally used to run all file system
operations, as well as getaddrinfo and getnameinfo requests.

Its default size is 4, but it can be changed at startup time by setting the
``UV_THREADPOOL_SIZE`` environment variable to any value (the absolute maximum
is 128).

The threadpool is global and shared across all event loops. When a particular
function makes use of the threadpool (i.e. when using :c:func:`uv_queue_work`)
libuv preallocates and initializes the maximum number of threads allowed by
``UV_THREADPOOL_SIZE``. This causes a relatively minor memory overhead
(~1MB for 128 threads) but increases the performance of threading at runtime.

.. note::
    Note that even though a global thread pool which is shared across all events
    loops is used, the functions are not thread safe.


Data types
----------

.. c:type:: uv_work_t

    Work request type.

libuv/src/threadpool.c  view on Meta::CPAN

static unsigned int slow_work_thread_threshold(void) {
  return (nthreads + 1) / 2;
}

static void uv__cancelled(struct uv__work* w) {
  abort();
}


/* To avoid deadlock with uv_cancel() it's crucial that the worker
 * never holds the global mutex and the loop-local mutex at the same time.
 */
static void worker(void* arg) {
  struct uv__work* w;
  QUEUE* q;
  int is_slow_work;

  uv_sem_post((uv_sem_t*) arg);
  arg = NULL;

  uv_mutex_lock(&mutex);

libuv/src/threadpool.c  view on Meta::CPAN

static void reset_once(void) {
  uv_once_t child_once = UV_ONCE_INIT;
  memcpy(&once, &child_once, sizeof(child_once));
}
#endif


static void init_once(void) {
#ifndef _WIN32
  /* Re-initialize the threadpool after fork.
   * Note that this discards the global mutex and condition as well
   * as the work queue.
   */
  if (pthread_atfork(NULL, NULL, &reset_once))
    abort();
#endif
  init_threads();
}


void uv__work_submit(uv_loop_t* loop,

libuv/src/unix/aix.c  view on Meta::CPAN


static void init_process_title_mutex_once(void) {
  uv_mutex_init(&process_title_mutex);
}


int uv__platform_loop_init(uv_loop_t* loop) {
  loop->fs_fd = -1;

  /* Passing maxfd of -1 should mean the limit is determined
   * by the user's ulimit or the global limit as per the doc */
  loop->backend_fd = pollset_create(-1);

  if (loop->backend_fd == -1)
    return -1;

  return 0;
}


void uv__platform_loop_delete(uv_loop_t* loop) {

libuv/src/unix/fsevents.c  view on Meta::CPAN

  unsigned int fsevent_handle_count;
};

/* Forward declarations */
static void uv__cf_loop_cb(void* arg);
static void* uv__cf_loop_runner(void* arg);
static int uv__cf_loop_signal(uv_loop_t* loop,
                              uv_fs_event_t* handle,
                              uv__cf_loop_signal_type_t type);

/* Lazy-loaded by uv__fsevents_global_init(). */
static CFArrayRef (*pCFArrayCreate)(CFAllocatorRef,
                                    const void**,
                                    CFIndex,
                                    const CFArrayCallBacks*);
static void (*pCFRelease)(CFTypeRef);
static void (*pCFRunLoopAddSource)(CFRunLoopRef,
                                   CFRunLoopSourceRef,
                                   CFStringRef);
static CFRunLoopRef (*pCFRunLoopGetCurrent)(void);
static void (*pCFRunLoopRemoveSource)(CFRunLoopRef,

libuv/src/unix/fsevents.c  view on Meta::CPAN

   * Main thread will block until the removal of handle from the list,
   * we must tell it when we're ready.
   *
   * NOTE: This is coupled with `uv_sem_wait()` in `uv__fsevents_close`
   */
  if (type == kUVCFLoopSignalClosing)
    uv_sem_post(&state->fsevent_sem);
}


static int uv__fsevents_global_init(void) {
  static pthread_mutex_t global_init_mutex = PTHREAD_MUTEX_INITIALIZER;
  static void* core_foundation_handle;
  static void* core_services_handle;
  int err;

  err = 0;
  pthread_mutex_lock(&global_init_mutex);
  if (core_foundation_handle != NULL)
    goto out;

  /* The libraries are never unloaded because we currently don't have a good
   * mechanism for keeping a reference count. It's unlikely to be an issue
   * but if it ever becomes one, we can turn the dynamic library handles into
   * per-event loop properties and have the dynamic linker keep track for us.
   */
  err = UV_ENOSYS;
  core_foundation_handle = dlopen("/System/Library/Frameworks/"

libuv/src/unix/fsevents.c  view on Meta::CPAN

  if (err && core_services_handle != NULL) {
    dlclose(core_services_handle);
    core_services_handle = NULL;
  }

  if (err && core_foundation_handle != NULL) {
    dlclose(core_foundation_handle);
    core_foundation_handle = NULL;
  }

  pthread_mutex_unlock(&global_init_mutex);
  return err;
}


/* Runs in UV loop */
static int uv__fsevents_loop_init(uv_loop_t* loop) {
  CFRunLoopSourceContext ctx;
  uv__cf_loop_state_t* state;
  pthread_attr_t attr_storage;
  pthread_attr_t* attr;
  int err;

  if (loop->cf_state != NULL)
    return 0;

  err = uv__fsevents_global_init();
  if (err)
    return err;

  state = uv__calloc(1, sizeof(*state));
  if (state == NULL)
    return UV_ENOMEM;

  err = uv_mutex_init(&loop->cf_mutex);
  if (err)
    goto fail_mutex_init;

libuv/src/unix/internal.h  view on Meta::CPAN

/* tcp */
int uv_tcp_listen(uv_tcp_t* tcp, int backlog, uv_connection_cb cb);
int uv__tcp_nodelay(int fd, int on);
int uv__tcp_keepalive(int fd, int on, unsigned int delay);

/* pipe */
int uv_pipe_listen(uv_pipe_t* handle, int backlog, uv_connection_cb cb);

/* signal */
void uv__signal_close(uv_signal_t* handle);
void uv__signal_global_once_init(void);
void uv__signal_loop_cleanup(uv_loop_t* loop);
int uv__signal_loop_fork(uv_loop_t* loop);

/* platform specific */
uint64_t uv__hrtime(uv_clocktype_t type);
int uv__kqueue_init(uv_loop_t* loop);
int uv__platform_loop_init(uv_loop_t* loop);
void uv__platform_loop_delete(uv_loop_t* loop);
void uv__platform_invalidate_fd(uv_loop_t* loop, int fd);

libuv/src/unix/loop.c  view on Meta::CPAN

  loop->backend_fd = -1;
  loop->emfile_fd = -1;

  loop->timer_counter = 0;
  loop->stop_flag = 0;

  err = uv__platform_loop_init(loop);
  if (err)
    return err;

  uv__signal_global_once_init();
  err = uv_signal_init(loop, &loop->child_watcher);
  if (err)
    goto fail_signal_init;

  uv__handle_unref(&loop->child_watcher);
  loop->child_watcher.flags |= UV_HANDLE_INTERNAL;
  QUEUE_INIT(&loop->process_handles);

  err = uv_rwlock_init(&loop->cloexec_lock);
  if (err)

libuv/src/unix/os390-syscalls.c  view on Meta::CPAN

#include <search.h>
#include <termios.h>
#include <sys/msg.h>

#define CW_CONDVAR 32

#pragma linkage(BPX4CTW, OS)
#pragma linkage(BPX1CTW, OS)

static int number_of_epolls;
static QUEUE global_epoll_queue;
static uv_mutex_t global_epoll_lock;
static uv_once_t once = UV_ONCE_INIT;

int scandir(const char* maindir, struct dirent*** namelist,
            int (*filter)(const struct dirent*),
            int (*compar)(const struct dirent**,
            const struct dirent **)) {
  struct dirent** nl;
  struct dirent* dirent;
  unsigned count;
  size_t allocated;

libuv/src/unix/os390-syscalls.c  view on Meta::CPAN

  if (msgsnd(lst->msg_queue, &msg, sizeof(msg.body), 0) != 0)
    abort();

  /* Clean up the dummy message sent above */
  if (msgrcv(lst->msg_queue, &msg, sizeof(msg.body), 0, 0) != sizeof(msg.body))
    abort();
}


static void before_fork(void) {
  uv_mutex_lock(&global_epoll_lock);
}


static void after_fork(void) {
  uv_mutex_unlock(&global_epoll_lock);
}


static void child_fork(void) {
  QUEUE* q;
  uv_once_t child_once = UV_ONCE_INIT;

  /* reset once */
  memcpy(&once, &child_once, sizeof(child_once));

  /* reset epoll list */
  while (!QUEUE_EMPTY(&global_epoll_queue)) {
    uv__os390_epoll* lst;
    q = QUEUE_HEAD(&global_epoll_queue);
    QUEUE_REMOVE(q);
    lst = QUEUE_DATA(q, uv__os390_epoll, member);
    uv__free(lst->items);
    lst->items = NULL;
    lst->size = 0;
  }

  uv_mutex_unlock(&global_epoll_lock);
  uv_mutex_destroy(&global_epoll_lock);
}


static void epoll_init(void) {
  QUEUE_INIT(&global_epoll_queue);
  if (uv_mutex_init(&global_epoll_lock))
    abort();

  if (pthread_atfork(&before_fork, &after_fork, &child_fork))
    abort();
}


uv__os390_epoll* epoll_create1(int flags) {
  uv__os390_epoll* lst;

libuv/src/unix/os390-syscalls.c  view on Meta::CPAN

  if (lst != NULL) {
    /* initialize list */
    lst->size = 0;
    lst->items = NULL;
    init_message_queue(lst);
    maybe_resize(lst, 1);
    lst->items[lst->size - 1].fd = lst->msg_queue;
    lst->items[lst->size - 1].events = POLLIN;
    lst->items[lst->size - 1].revents = 0;
    uv_once(&once, epoll_init);
    uv_mutex_lock(&global_epoll_lock);
    QUEUE_INSERT_TAIL(&global_epoll_queue, &lst->member);
    uv_mutex_unlock(&global_epoll_lock);
  }

  return lst;
}


int epoll_ctl(uv__os390_epoll* lst,
              int op,
              int fd,
              struct epoll_event *event) {
  uv_mutex_lock(&global_epoll_lock);

  if (op == EPOLL_CTL_DEL) {
    if (fd >= lst->size || lst->items[fd].fd == -1) {
      uv_mutex_unlock(&global_epoll_lock);
      errno = ENOENT;
      return -1;
    }
    lst->items[fd].fd = -1;
  } else if (op == EPOLL_CTL_ADD) {

    /* Resizing to 'fd + 1' would expand the list to contain at least
     * 'fd'. But we need to guarantee that the last index on the list 
     * is reserved for the message queue. So specify 'fd + 2' instead.
     */
    maybe_resize(lst, fd + 2);
    if (lst->items[fd].fd != -1) {
      uv_mutex_unlock(&global_epoll_lock);
      errno = EEXIST;
      return -1;
    }
    lst->items[fd].fd = fd;
    lst->items[fd].events = event->events;
    lst->items[fd].revents = 0;
  } else if (op == EPOLL_CTL_MOD) {
    if (fd >= lst->size - 1 || lst->items[fd].fd == -1) {
      uv_mutex_unlock(&global_epoll_lock);
      errno = ENOENT;
      return -1;
    }
    lst->items[fd].events = event->events;
    lst->items[fd].revents = 0;
  } else
    abort();

  uv_mutex_unlock(&global_epoll_lock);
  return 0;
}


int epoll_wait(uv__os390_epoll* lst, struct epoll_event* events,
               int maxevents, int timeout) {
  nmsgsfds_t size;
  struct pollfd* pfds;
  int pollret;
  int reventcount;

libuv/src/unix/os390-syscalls.c  view on Meta::CPAN

  }

  return nevents;
}


int epoll_file_close(int fd) {
  QUEUE* q;

  uv_once(&once, epoll_init);
  uv_mutex_lock(&global_epoll_lock);
  QUEUE_FOREACH(q, &global_epoll_queue) {
    uv__os390_epoll* lst;

    lst = QUEUE_DATA(q, uv__os390_epoll, member);
    if (fd < lst->size && lst->items != NULL && lst->items[fd].fd != -1)
      lst->items[fd].fd = -1;
  }

  uv_mutex_unlock(&global_epoll_lock);
  return 0;
}

void epoll_queue_close(uv__os390_epoll* lst) {
  /* Remove epoll instance from global queue */
  uv_mutex_lock(&global_epoll_lock);
  QUEUE_REMOVE(&lst->member);
  uv_mutex_unlock(&global_epoll_lock);

  /* Free resources */
  msgctl(lst->msg_queue, IPC_RMID, NULL);
  lst->msg_queue = -1;
  uv__free(lst->items);
  lst->items = NULL;
}


int nanosleep(const struct timespec* req, struct timespec* rem) {

libuv/src/unix/signal.c  view on Meta::CPAN

static int uv__signal_start(uv_signal_t* handle,
                            uv_signal_cb signal_cb,
                            int signum,
                            int oneshot);
static void uv__signal_event(uv_loop_t* loop, uv__io_t* w, unsigned int events);
static int uv__signal_compare(uv_signal_t* w1, uv_signal_t* w2);
static void uv__signal_stop(uv_signal_t* handle);
static void uv__signal_unregister_handler(int signum);


static uv_once_t uv__signal_global_init_guard = UV_ONCE_INIT;
static struct uv__signal_tree_s uv__signal_tree =
    RB_INITIALIZER(uv__signal_tree);
static int uv__signal_lock_pipefd[2] = { -1, -1 };

RB_GENERATE_STATIC(uv__signal_tree_s,
                   uv_signal_s, tree_entry,
                   uv__signal_compare)

static void uv__signal_global_reinit(void);

static void uv__signal_global_init(void) {
  if (uv__signal_lock_pipefd[0] == -1)
    /* pthread_atfork can register before and after handlers, one
     * for each child. This only registers one for the child. That
     * state is both persistent and cumulative, so if we keep doing
     * it the handler functions will be called multiple times. Thus
     * we only want to do it once.
     */
    if (pthread_atfork(NULL, NULL, &uv__signal_global_reinit))
      abort();

  uv__signal_global_reinit();
}


UV_DESTRUCTOR(static void uv__signal_global_fini(void)) {
  /* We can only use signal-safe functions here.
   * That includes read/write and close, fortunately.
   * We do all of this directly here instead of resetting
   * uv__signal_global_init_guard because
   * uv__signal_global_once_init is only called from uv_loop_init
   * and this needs to function in existing loops.
   */
  if (uv__signal_lock_pipefd[0] != -1) {
    uv__close(uv__signal_lock_pipefd[0]);
    uv__signal_lock_pipefd[0] = -1;
  }

  if (uv__signal_lock_pipefd[1] != -1) {
    uv__close(uv__signal_lock_pipefd[1]);
    uv__signal_lock_pipefd[1] = -1;
  }
}


static void uv__signal_global_reinit(void) {
  uv__signal_global_fini();

  if (uv__make_pipe(uv__signal_lock_pipefd, 0))
    abort();

  if (uv__signal_unlock())
    abort();
}


void uv__signal_global_once_init(void) {
  uv_once(&uv__signal_global_init_guard, uv__signal_global_init);
}


static int uv__signal_lock(void) {
  int r;
  char data;

  do {
    r = read(uv__signal_lock_pipefd[0], &data, sizeof data);
  } while (r < 0 && errno == EINTR);

libuv/src/win/process.c  view on Meta::CPAN

  E_V("SYSTEMROOT"),
  E_V("TEMP"),
  E_V("USERDOMAIN"),
  E_V("USERNAME"),
  E_V("USERPROFILE"),
  E_V("WINDIR"),
};
static size_t n_required_vars = ARRAY_SIZE(required_vars);


static HANDLE uv_global_job_handle_;
static uv_once_t uv_global_job_handle_init_guard_ = UV_ONCE_INIT;


static void uv__init_global_job_handle(void) {
  /* Create a job object and set it up to kill all contained processes when
   * it's closed. Since this handle is made non-inheritable and we're not
   * giving it to anyone, we're the only process holding a reference to it.
   * That means that if this process exits it is closed and all the processes
   * it contains are killed. All processes created with uv_spawn that are not
   * spawned with the UV_PROCESS_DETACHED flag are assigned to this job.
   *
   * We're setting the JOB_OBJECT_LIMIT_SILENT_BREAKAWAY_OK flag so only the
   * processes that we explicitly add are affected, and *their* subprocesses
   * are not. This ensures that our child processes are not limited in their

libuv/src/win/process.c  view on Meta::CPAN

  memset(&attr, 0, sizeof attr);
  attr.bInheritHandle = FALSE;

  memset(&info, 0, sizeof info);
  info.BasicLimitInformation.LimitFlags =
      JOB_OBJECT_LIMIT_BREAKAWAY_OK |
      JOB_OBJECT_LIMIT_SILENT_BREAKAWAY_OK |
      JOB_OBJECT_LIMIT_DIE_ON_UNHANDLED_EXCEPTION |
      JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE;

  uv_global_job_handle_ = CreateJobObjectW(&attr, NULL);
  if (uv_global_job_handle_ == NULL)
    uv_fatal_error(GetLastError(), "CreateJobObjectW");

  if (!SetInformationJobObject(uv_global_job_handle_,
                               JobObjectExtendedLimitInformation,
                               &info,
                               sizeof info))
    uv_fatal_error(GetLastError(), "SetInformationJobObject");
}


static int uv_utf8_to_utf16_alloc(const char* s, WCHAR** ws_ptr) {
  int ws_len, r;
  WCHAR* ws;

libuv/src/win/process.c  view on Meta::CPAN

    /* CreateProcessW failed. */
    err = GetLastError();
    goto done;
  }

  /* Spawn succeeded. Beyond this point, failure is reported asynchronously. */

  process->process_handle = info.hProcess;
  process->pid = info.dwProcessId;

  /* If the process isn't spawned as detached, assign to the global job object
   * so windows will kill it when the parent process dies. */
  if (!(options->flags & UV_PROCESS_DETACHED)) {
    uv_once(&uv_global_job_handle_init_guard_, uv__init_global_job_handle);

    if (!AssignProcessToJobObject(uv_global_job_handle_, info.hProcess)) {
      /* AssignProcessToJobObject might fail if this process is under job
       * control and the job doesn't have the
       * JOB_OBJECT_LIMIT_SILENT_BREAKAWAY_OK flag set, on a Windows version
       * that doesn't support nested jobs.
       *
       * When that happens we just swallow the error and continue without
       * establishing a kill-child-on-parent-exit relationship, otherwise
       * there would be no way for libuv applications run under job control
       * to spawn processes at all.
       */

libuv/test/test-loop-handles.c  view on Meta::CPAN

 * - All active idle watchers are queued when the event loop has no more work
 *   to do. This is done repeatedly until all idle watchers are inactive.
 * - If a watcher starts another watcher of the same type its callback is not
 *   immediately queued. For check and prepare watchers, that means that if
 *   a watcher makes another of the same type active, it'll not be called until
 *   the next event loop iteration. For idle. watchers this means that the
 *   newly activated idle watcher might not be queued immediately.
 * - Prepare, check, idle watchers keep the event loop alive even when they're
 *   not active.
 *
 * This is what the test globally does:
 *
 * - prepare_1 is always active and counts event loop iterations. It also
 *   creates and starts prepare_2 every other iteration. Finally it verifies
 *   that no idle watchers are active before polling.
 * - prepare_2 is started by prepare_1 every other iteration. It immediately
 *   stops itself. It verifies that a watcher is not queued immediately
 *   if created by another watcher of the same type.
 * - There's a check watcher that stops the event loop after a certain number
 *   of iterations. It starts a varying number of idle_1 watchers.
 * - Idle_1 watchers stop themselves after being called a few times. All idle_1



( run in 1.472 second using v1.01-cache-2.11-cpan-49f99fa48dc )