passenger 5.0.25 → 5.0.26

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of passenger might be problematic. Click here for more details.

Files changed (128) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG +20 -0
  3. data/CONTRIBUTORS +1 -0
  4. data/build/cxx_dependency_map.rb +7338 -7104
  5. data/build/cxx_tests.rb +3 -3
  6. data/build/misc.rb +1 -0
  7. data/dev/index_cxx_dependencies.rb +3 -2
  8. data/resources/templates/standalone/config.erb +1 -1
  9. data/resources/templates/standalone/http.erb +1 -0
  10. data/resources/templates/standalone/server.erb +1 -0
  11. data/src/agent/Core/ApplicationPool/AbstractSession.h +83 -0
  12. data/src/agent/Core/ApplicationPool/Common.h +6 -4
  13. data/src/agent/Core/ApplicationPool/Options.h +4 -1
  14. data/src/agent/Core/ApplicationPool/Pool.h +2 -2
  15. data/src/agent/Core/ApplicationPool/Pool/AnalyticsCollection.cpp +3 -6
  16. data/src/agent/Core/ApplicationPool/Pool/GeneralUtils.cpp +3 -3
  17. data/src/agent/Core/ApplicationPool/Session.h +15 -27
  18. data/src/agent/Core/ApplicationPool/TestSession.h +188 -0
  19. data/src/agent/Core/Controller.h +15 -6
  20. data/src/agent/Core/Controller/CheckoutSession.cpp +13 -5
  21. data/src/agent/Core/Controller/ForwardResponse.cpp +20 -2
  22. data/src/agent/Core/Controller/Hooks.cpp +15 -2
  23. data/src/agent/Core/Controller/InitRequest.cpp +5 -1
  24. data/src/agent/Core/Controller/InitializationAndShutdown.cpp +1 -0
  25. data/src/agent/Core/Controller/Request.h +11 -4
  26. data/src/agent/Core/Controller/SendRequest.cpp +34 -13
  27. data/src/agent/Core/Controller/StateInspectionAndConfiguration.cpp +2 -2
  28. data/src/agent/Core/CoreMain.cpp +27 -1
  29. data/src/agent/Core/OptionParser.h +11 -1
  30. data/src/agent/Core/SpawningKit/DirectSpawner.h +1 -0
  31. data/src/agent/Core/SpawningKit/SmartSpawner.h +1 -0
  32. data/src/agent/Core/SpawningKit/Spawner.h +21 -1
  33. data/src/agent/SpawnPreparer/SpawnPreparerMain.cpp +1 -1
  34. data/src/agent/UstRouter/OptionParser.h +7 -1
  35. data/src/agent/UstRouter/UstRouterMain.cpp +27 -1
  36. data/src/cxx_supportlib/Algorithms/MovingAverage.h +223 -0
  37. data/src/cxx_supportlib/Constants.h +2 -2
  38. data/src/cxx_supportlib/DataStructures/StringKeyTable.h +96 -40
  39. data/src/cxx_supportlib/ResourceLocator.h +33 -14
  40. data/src/cxx_supportlib/ServerKit/Channel.h +198 -69
  41. data/src/cxx_supportlib/ServerKit/Errors.h +6 -1
  42. data/src/cxx_supportlib/ServerKit/HttpRequest.h +20 -1
  43. data/src/cxx_supportlib/ServerKit/HttpServer.h +124 -32
  44. data/src/cxx_supportlib/ServerKit/Server.h +65 -1
  45. data/src/cxx_supportlib/Utils/IOUtils.cpp +12 -22
  46. data/src/cxx_supportlib/Utils/JsonUtils.h +87 -1
  47. data/src/cxx_supportlib/Utils/StrIntUtils.cpp +16 -1
  48. data/src/cxx_supportlib/Utils/StrIntUtils.h +31 -1
  49. data/src/cxx_supportlib/Utils/VariantMap.h +6 -1
  50. data/src/cxx_supportlib/WatchdogLauncher.h +17 -9
  51. data/src/cxx_supportlib/vendor-copy/libuv/AUTHORS +43 -0
  52. data/src/cxx_supportlib/vendor-copy/libuv/ChangeLog +350 -1
  53. data/src/cxx_supportlib/vendor-copy/libuv/Makefile.am +9 -1
  54. data/src/cxx_supportlib/vendor-copy/libuv/README.md +48 -0
  55. data/src/cxx_supportlib/vendor-copy/libuv/checksparse.sh +1 -0
  56. data/src/cxx_supportlib/vendor-copy/libuv/common.gypi +5 -5
  57. data/src/cxx_supportlib/vendor-copy/libuv/configure.ac +2 -1
  58. data/src/cxx_supportlib/vendor-copy/libuv/gyp_uv.py +0 -3
  59. data/src/cxx_supportlib/vendor-copy/libuv/include/uv-version.h +5 -1
  60. data/src/cxx_supportlib/vendor-copy/libuv/include/uv.h +30 -3
  61. data/src/cxx_supportlib/vendor-copy/libuv/src/fs-poll.c +3 -3
  62. data/src/cxx_supportlib/vendor-copy/libuv/src/inet.c +0 -4
  63. data/src/cxx_supportlib/vendor-copy/libuv/src/queue.h +17 -1
  64. data/src/cxx_supportlib/vendor-copy/libuv/src/threadpool.c +10 -10
  65. data/src/cxx_supportlib/vendor-copy/libuv/src/unix/aix.c +84 -166
  66. data/src/cxx_supportlib/vendor-copy/libuv/src/unix/android-ifaddrs.c +11 -11
  67. data/src/cxx_supportlib/vendor-copy/libuv/src/unix/async.c +7 -1
  68. data/src/cxx_supportlib/vendor-copy/libuv/src/unix/atomic-ops.h +17 -0
  69. data/src/cxx_supportlib/vendor-copy/libuv/src/unix/core.c +140 -21
  70. data/src/cxx_supportlib/vendor-copy/libuv/src/unix/darwin.c +15 -11
  71. data/src/cxx_supportlib/vendor-copy/libuv/src/unix/dl.c +4 -7
  72. data/src/cxx_supportlib/vendor-copy/libuv/src/unix/freebsd.c +52 -37
  73. data/src/cxx_supportlib/vendor-copy/libuv/src/unix/fs.c +181 -60
  74. data/src/cxx_supportlib/vendor-copy/libuv/src/unix/fsevents.c +39 -34
  75. data/src/cxx_supportlib/vendor-copy/libuv/src/unix/getaddrinfo.c +4 -4
  76. data/src/cxx_supportlib/vendor-copy/libuv/src/unix/internal.h +3 -1
  77. data/src/cxx_supportlib/vendor-copy/libuv/src/unix/kqueue.c +12 -4
  78. data/src/cxx_supportlib/vendor-copy/libuv/src/unix/linux-core.c +38 -15
  79. data/src/cxx_supportlib/vendor-copy/libuv/src/unix/linux-inotify.c +36 -8
  80. data/src/cxx_supportlib/vendor-copy/libuv/src/unix/linux-syscalls.c +4 -4
  81. data/src/cxx_supportlib/vendor-copy/libuv/src/unix/linux-syscalls.h +2 -2
  82. data/src/cxx_supportlib/vendor-copy/libuv/src/unix/loop-watcher.c +6 -1
  83. data/src/cxx_supportlib/vendor-copy/libuv/src/unix/loop.c +28 -8
  84. data/src/cxx_supportlib/vendor-copy/libuv/src/unix/netbsd.c +18 -16
  85. data/src/cxx_supportlib/vendor-copy/libuv/src/unix/openbsd.c +18 -16
  86. data/src/cxx_supportlib/vendor-copy/libuv/src/unix/pipe.c +3 -3
  87. data/src/cxx_supportlib/vendor-copy/libuv/src/unix/process.c +18 -6
  88. data/src/cxx_supportlib/vendor-copy/libuv/src/unix/proctitle.c +2 -2
  89. data/src/cxx_supportlib/vendor-copy/libuv/src/unix/pthread-fixes.c +1 -0
  90. data/src/cxx_supportlib/vendor-copy/libuv/src/unix/signal.c +2 -0
  91. data/src/cxx_supportlib/vendor-copy/libuv/src/unix/stream.c +47 -30
  92. data/src/cxx_supportlib/vendor-copy/libuv/src/unix/sunos.c +13 -11
  93. data/src/cxx_supportlib/vendor-copy/libuv/src/unix/tcp.c +43 -8
  94. data/src/cxx_supportlib/vendor-copy/libuv/src/unix/thread.c +21 -15
  95. data/src/cxx_supportlib/vendor-copy/libuv/src/unix/tty.c +16 -2
  96. data/src/cxx_supportlib/vendor-copy/libuv/src/unix/udp.c +54 -14
  97. data/src/cxx_supportlib/vendor-copy/libuv/src/uv-common.c +104 -21
  98. data/src/cxx_supportlib/vendor-copy/libuv/src/uv-common.h +14 -1
  99. data/src/cxx_supportlib/vendor-copy/libuv/src/version.c +1 -5
  100. data/src/cxx_supportlib/vendor-copy/libuv/uv.gyp +22 -1
  101. data/src/nginx_module/CacheLocationConfig.c +52 -0
  102. data/src/nginx_module/CacheLocationConfig.c.erb +13 -1
  103. data/src/nginx_module/Configuration.c +1 -0
  104. data/src/nginx_module/Configuration.h +1 -0
  105. data/src/nginx_module/ConfigurationCommands.c +20 -0
  106. data/src/nginx_module/ConfigurationFields.h +4 -0
  107. data/src/nginx_module/CreateLocationConfig.c +8 -0
  108. data/src/nginx_module/MergeLocationConfig.c +12 -0
  109. data/src/nginx_module/config +31 -13
  110. data/src/nginx_module/ngx_http_passenger_module.c +4 -0
  111. data/src/ruby_supportlib/phusion_passenger.rb +1 -1
  112. data/src/ruby_supportlib/phusion_passenger/constants.rb +1 -1
  113. data/src/ruby_supportlib/phusion_passenger/nginx/config_options.rb +11 -1
  114. data/src/ruby_supportlib/phusion_passenger/platform_info/apache.rb +6 -1
  115. data/src/ruby_supportlib/phusion_passenger/rack/thread_handler_extension.rb +32 -31
  116. data/src/ruby_supportlib/phusion_passenger/standalone/config_options_list.rb +13 -2
  117. data/src/ruby_supportlib/phusion_passenger/standalone/config_utils.rb +1 -0
  118. data/src/ruby_supportlib/phusion_passenger/standalone/start_command/builtin_engine.rb +6 -1
  119. data/src/ruby_supportlib/phusion_passenger/vendor/union_station_hooks_core/lib/union_station_hooks_core.rb +6 -0
  120. data/src/ruby_supportlib/phusion_passenger/vendor/union_station_hooks_core/lib/union_station_hooks_core/api.rb +29 -19
  121. data/src/ruby_supportlib/phusion_passenger/vendor/union_station_hooks_core/lib/union_station_hooks_core/context.rb +2 -2
  122. data/src/ruby_supportlib/phusion_passenger/vendor/union_station_hooks_core/lib/union_station_hooks_core/request_reporter.rb +2 -3
  123. data/src/ruby_supportlib/phusion_passenger/vendor/union_station_hooks_core/lib/union_station_hooks_core/simple_json.rb +2 -1
  124. data/src/ruby_supportlib/phusion_passenger/vendor/union_station_hooks_core/lib/union_station_hooks_core/spec_helper.rb +2 -0
  125. data/src/ruby_supportlib/phusion_passenger/vendor/union_station_hooks_core/lib/union_station_hooks_core/time_point.rb +3 -17
  126. data/src/ruby_supportlib/phusion_passenger/vendor/union_station_hooks_core/lib/union_station_hooks_core/transaction.rb +7 -10
  127. data/src/ruby_supportlib/phusion_passenger/vendor/union_station_hooks_core/lib/union_station_hooks_core/utils.rb +11 -9
  128. metadata +5 -2
@@ -55,7 +55,7 @@ char** uv_setup_args(int argc, char** argv) {
55
55
  /* Add space for the argv pointers. */
56
56
  size += (argc + 1) * sizeof(char*);
57
57
 
58
- new_argv = malloc(size);
58
+ new_argv = uv__malloc(size);
59
59
  if (new_argv == NULL)
60
60
  return argv;
61
61
  args_mem = new_argv;
@@ -97,6 +97,6 @@ int uv_get_process_title(char* buffer, size_t size) {
97
97
 
98
98
 
99
99
  UV_DESTRUCTOR(static void free_args_mem(void)) {
100
- free(args_mem); /* Keep valgrind happy. */
100
+ uv__free(args_mem); /* Keep valgrind happy. */
101
101
  args_mem = NULL;
102
102
  }
@@ -35,6 +35,7 @@
35
35
  * */
36
36
  #include <errno.h>
37
37
  #include <pthread.h>
38
+ #include <signal.h>
38
39
 
39
40
  int uv__pthread_sigmask(int how, const sigset_t* set, sigset_t* oset) {
40
41
  static int workaround;
@@ -234,6 +234,8 @@ void uv__signal_loop_cleanup(uv_loop_t* loop) {
234
234
  /* Stop all the signal watchers that are still attached to this loop. This
235
235
  * ensures that the (shared) signal tree doesn't contain any invalid entries
236
236
  * entries, and that signal handlers are removed when appropriate.
237
+ * It's safe to use QUEUE_FOREACH here because the handles and the handle
238
+ * queue are not modified by uv__signal_stop().
237
239
  */
238
240
  QUEUE_FOREACH(q, &loop->handle_queue) {
239
241
  uv_handle_t* handle = QUEUE_DATA(q, uv_handle_t, handle_queue);
@@ -231,7 +231,6 @@ static void uv__stream_osx_select_cb(uv_async_t* handle) {
231
231
  /* Get and reset stream's events */
232
232
  events = s->events;
233
233
  ACCESS_ONCE(int, s->events) = 0;
234
- uv_sem_post(&s->async_sem);
235
234
 
236
235
  assert(events != 0);
237
236
  assert(events == (events & (UV__POLLIN | UV__POLLOUT)));
@@ -242,6 +241,14 @@ static void uv__stream_osx_select_cb(uv_async_t* handle) {
242
241
 
243
242
  if ((events & UV__POLLOUT) && uv__io_active(&stream->io_watcher, UV__POLLOUT))
244
243
  uv__stream_io(stream->loop, &stream->io_watcher, UV__POLLOUT);
244
+
245
+ if (stream->flags & UV_CLOSING)
246
+ return;
247
+
248
+ /* NOTE: It is important to do it here, otherwise `select()` might be called
249
+ * before the actual `uv__read()`, leading to the blocking syscall
250
+ */
251
+ uv_sem_post(&s->async_sem);
245
252
  }
246
253
 
247
254
 
@@ -249,7 +256,7 @@ static void uv__stream_osx_cb_close(uv_handle_t* async) {
249
256
  uv__stream_select_t* s;
250
257
 
251
258
  s = container_of(async, uv__stream_select_t, async);
252
- free(s);
259
+ uv__free(s);
253
260
  }
254
261
 
255
262
 
@@ -309,7 +316,7 @@ int uv__stream_try_select(uv_stream_t* stream, int* fd) {
309
316
  sread_sz = ROUND_UP(max_fd + 1, sizeof(uint32_t) * NBBY) / NBBY;
310
317
  swrite_sz = sread_sz;
311
318
 
312
- s = malloc(sizeof(*s) + sread_sz + swrite_sz);
319
+ s = uv__malloc(sizeof(*s) + sread_sz + swrite_sz);
313
320
  if (s == NULL) {
314
321
  err = -ENOMEM;
315
322
  goto failed_malloc;
@@ -368,7 +375,7 @@ failed_close_sem_init:
368
375
  return err;
369
376
 
370
377
  failed_async_init:
371
- free(s);
378
+ uv__free(s);
372
379
 
373
380
  failed_malloc:
374
381
  uv__close(fds[0]);
@@ -384,6 +391,9 @@ int uv__stream_open(uv_stream_t* stream, int fd, int flags) {
384
391
  int enable;
385
392
  #endif
386
393
 
394
+ if (!(stream->io_watcher.fd == -1 || stream->io_watcher.fd == fd))
395
+ return -EBUSY;
396
+
387
397
  assert(fd >= 0);
388
398
  stream->flags |= flags;
389
399
 
@@ -605,7 +615,7 @@ done:
605
615
  /* All read, free */
606
616
  assert(queued_fds->offset > 0);
607
617
  if (--queued_fds->offset == 0) {
608
- free(queued_fds);
618
+ uv__free(queued_fds);
609
619
  server->queued_fds = NULL;
610
620
  } else {
611
621
  /* Shift rest */
@@ -703,7 +713,7 @@ static void uv__write_req_finish(uv_write_t* req) {
703
713
  */
704
714
  if (req->error == 0) {
705
715
  if (req->bufs != req->bufsml)
706
- free(req->bufs);
716
+ uv__free(req->bufs);
707
717
  req->bufs = NULL;
708
718
  }
709
719
 
@@ -729,19 +739,6 @@ static int uv__handle_fd(uv_handle_t* handle) {
729
739
  }
730
740
  }
731
741
 
732
- static int uv__getiovmax() {
733
- #if defined(IOV_MAX)
734
- return IOV_MAX;
735
- #elif defined(_SC_IOV_MAX)
736
- static int iovmax = -1;
737
- if (iovmax == -1)
738
- iovmax = sysconf(_SC_IOV_MAX);
739
- return iovmax;
740
- #else
741
- return 1024;
742
- #endif
743
- }
744
-
745
742
  static void uv__write(uv_stream_t* stream) {
746
743
  struct iovec* iov;
747
744
  QUEUE* q;
@@ -782,9 +779,9 @@ start:
782
779
 
783
780
  if (req->send_handle) {
784
781
  struct msghdr msg;
785
- char scratch[64];
786
782
  struct cmsghdr *cmsg;
787
783
  int fd_to_send = uv__handle_fd((uv_handle_t*) req->send_handle);
784
+ char scratch[64] = {0};
788
785
 
789
786
  assert(fd_to_send >= 0);
790
787
 
@@ -812,7 +809,17 @@ start:
812
809
  do {
813
810
  n = sendmsg(uv__stream_fd(stream), &msg, 0);
814
811
  }
812
+ #if defined(__APPLE__)
813
+ /*
814
+ * Due to a possible kernel bug at least in OS X 10.10 "Yosemite",
815
+ * EPROTOTYPE can be returned while trying to write to a socket that is
816
+ * shutting down. If we retry the write, we should get the expected EPIPE
817
+ * instead.
818
+ */
819
+ while (n == -1 && (errno == EINTR || errno == EPROTOTYPE));
820
+ #else
815
821
  while (n == -1 && errno == EINTR);
822
+ #endif
816
823
  } else {
817
824
  do {
818
825
  if (iovcnt == 1) {
@@ -821,7 +828,17 @@ start:
821
828
  n = writev(uv__stream_fd(stream), iov, iovcnt);
822
829
  }
823
830
  }
831
+ #if defined(__APPLE__)
832
+ /*
833
+ * Due to a possible kernel bug at least in OS X 10.10 "Yosemite",
834
+ * EPROTOTYPE can be returned while trying to write to a socket that is
835
+ * shutting down. If we retry the write, we should get the expected EPIPE
836
+ * instead.
837
+ */
838
+ while (n == -1 && (errno == EINTR || errno == EPROTOTYPE));
839
+ #else
824
840
  while (n == -1 && errno == EINTR);
841
+ #endif
825
842
  }
826
843
 
827
844
  if (n < 0) {
@@ -914,7 +931,7 @@ static void uv__write_callbacks(uv_stream_t* stream) {
914
931
  if (req->bufs != NULL) {
915
932
  stream->write_queue_size -= uv__write_req_size(req);
916
933
  if (req->bufs != req->bufsml)
917
- free(req->bufs);
934
+ uv__free(req->bufs);
918
935
  req->bufs = NULL;
919
936
  }
920
937
 
@@ -979,8 +996,8 @@ static int uv__stream_queue_fd(uv_stream_t* stream, int fd) {
979
996
  queued_fds = stream->queued_fds;
980
997
  if (queued_fds == NULL) {
981
998
  queue_size = 8;
982
- queued_fds = malloc((queue_size - 1) * sizeof(*queued_fds->fds) +
983
- sizeof(*queued_fds));
999
+ queued_fds = uv__malloc((queue_size - 1) * sizeof(*queued_fds->fds) +
1000
+ sizeof(*queued_fds));
984
1001
  if (queued_fds == NULL)
985
1002
  return -ENOMEM;
986
1003
  queued_fds->size = queue_size;
@@ -990,9 +1007,9 @@ static int uv__stream_queue_fd(uv_stream_t* stream, int fd) {
990
1007
  /* Grow */
991
1008
  } else if (queued_fds->size == queued_fds->offset) {
992
1009
  queue_size = queued_fds->size + 8;
993
- queued_fds = realloc(queued_fds,
994
- (queue_size - 1) * sizeof(*queued_fds->fds) +
995
- sizeof(*queued_fds));
1010
+ queued_fds = uv__realloc(queued_fds,
1011
+ (queue_size - 1) * sizeof(*queued_fds->fds) +
1012
+ sizeof(*queued_fds));
996
1013
 
997
1014
  /*
998
1015
  * Allocation failure, report back.
@@ -1357,7 +1374,7 @@ int uv_write2(uv_write_t* req,
1357
1374
 
1358
1375
  req->bufs = req->bufsml;
1359
1376
  if (nbufs > ARRAY_SIZE(req->bufsml))
1360
- req->bufs = malloc(nbufs * sizeof(bufs[0]));
1377
+ req->bufs = uv__malloc(nbufs * sizeof(bufs[0]));
1361
1378
 
1362
1379
  if (req->bufs == NULL)
1363
1380
  return -ENOMEM;
@@ -1445,7 +1462,7 @@ int uv_try_write(uv_stream_t* stream,
1445
1462
  QUEUE_REMOVE(&req.queue);
1446
1463
  uv__req_unregister(stream->loop, &req);
1447
1464
  if (req.bufs != req.bufsml)
1448
- free(req.bufs);
1465
+ uv__free(req.bufs);
1449
1466
  req.bufs = NULL;
1450
1467
 
1451
1468
  /* Do not poll for writable, if we wasn't before calling this */
@@ -1454,7 +1471,7 @@ int uv_try_write(uv_stream_t* stream,
1454
1471
  uv__stream_osx_interrupt_select(stream);
1455
1472
  }
1456
1473
 
1457
- if (written == 0)
1474
+ if (written == 0 && req_size != 0)
1458
1475
  return -EAGAIN;
1459
1476
  else
1460
1477
  return written;
@@ -1582,7 +1599,7 @@ void uv__stream_close(uv_stream_t* handle) {
1582
1599
  queued_fds = handle->queued_fds;
1583
1600
  for (i = 0; i < queued_fds->offset; i++)
1584
1601
  uv__close(queued_fds->fds[i]);
1585
- free(handle->queued_fds);
1602
+ uv__free(handle->queued_fds);
1586
1603
  handle->queued_fds = NULL;
1587
1604
  }
1588
1605
 
@@ -433,7 +433,7 @@ int uv_fs_event_start(uv_fs_event_t* handle,
433
433
  }
434
434
 
435
435
  uv__handle_start(handle);
436
- handle->path = strdup(path);
436
+ handle->path = uv__strdup(path);
437
437
  handle->fd = PORT_UNUSED;
438
438
  handle->cb = cb;
439
439
 
@@ -463,7 +463,7 @@ int uv_fs_event_stop(uv_fs_event_t* handle) {
463
463
  }
464
464
 
465
465
  handle->fd = PORT_DELETED;
466
- free(handle->path);
466
+ uv__free(handle->path);
467
467
  handle->path = NULL;
468
468
  handle->fo.fo_name = NULL;
469
469
  uv__handle_stop(handle);
@@ -582,7 +582,7 @@ int uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count) {
582
582
  lookup_instance++;
583
583
  }
584
584
 
585
- *cpu_infos = malloc(lookup_instance * sizeof(**cpu_infos));
585
+ *cpu_infos = uv__malloc(lookup_instance * sizeof(**cpu_infos));
586
586
  if (!(*cpu_infos)) {
587
587
  kstat_close(kc);
588
588
  return -ENOMEM;
@@ -605,7 +605,7 @@ int uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count) {
605
605
 
606
606
  knp = kstat_data_lookup(ksp, (char*) "brand");
607
607
  assert(knp->data_type == KSTAT_DATA_STRING);
608
- cpu_info->model = strdup(KSTAT_NAMED_STR_PTR(knp));
608
+ cpu_info->model = uv__strdup(KSTAT_NAMED_STR_PTR(knp));
609
609
  }
610
610
 
611
611
  lookup_instance++;
@@ -659,10 +659,10 @@ void uv_free_cpu_info(uv_cpu_info_t* cpu_infos, int count) {
659
659
  int i;
660
660
 
661
661
  for (i = 0; i < count; i++) {
662
- free(cpu_infos[i].model);
662
+ uv__free(cpu_infos[i].model);
663
663
  }
664
664
 
665
- free(cpu_infos);
665
+ uv__free(cpu_infos);
666
666
  }
667
667
 
668
668
 
@@ -692,9 +692,11 @@ int uv_interface_addresses(uv_interface_address_t** addresses, int* count) {
692
692
  (*count)++;
693
693
  }
694
694
 
695
- *addresses = malloc(*count * sizeof(**addresses));
696
- if (!(*addresses))
695
+ *addresses = uv__malloc(*count * sizeof(**addresses));
696
+ if (!(*addresses)) {
697
+ freeifaddrs(addrs);
697
698
  return -ENOMEM;
699
+ }
698
700
 
699
701
  address = *addresses;
700
702
 
@@ -705,7 +707,7 @@ int uv_interface_addresses(uv_interface_address_t** addresses, int* count) {
705
707
  if (ent->ifa_addr == NULL)
706
708
  continue;
707
709
 
708
- address->name = strdup(ent->ifa_name);
710
+ address->name = uv__strdup(ent->ifa_name);
709
711
 
710
712
  if (ent->ifa_addr->sa_family == AF_INET6) {
711
713
  address->address.address6 = *((struct sockaddr_in6*) ent->ifa_addr);
@@ -756,8 +758,8 @@ void uv_free_interface_addresses(uv_interface_address_t* addresses,
756
758
  int i;
757
759
 
758
760
  for (i = 0; i < count; i++) {
759
- free(addresses[i].name);
761
+ uv__free(addresses[i].name);
760
762
  }
761
763
 
762
- free(addresses);
764
+ uv__free(addresses);
763
765
  }
@@ -28,18 +28,14 @@
28
28
  #include <errno.h>
29
29
 
30
30
 
31
- int uv_tcp_init(uv_loop_t* loop, uv_tcp_t* tcp) {
32
- uv__stream_init(loop, (uv_stream_t*)tcp, UV_TCP);
33
- return 0;
34
- }
35
-
36
-
37
31
  static int maybe_new_socket(uv_tcp_t* handle, int domain, int flags) {
38
32
  int sockfd;
39
33
  int err;
40
34
 
41
- if (uv__stream_fd(handle) != -1)
35
+ if (domain == AF_UNSPEC || uv__stream_fd(handle) != -1) {
36
+ handle->flags |= flags;
42
37
  return 0;
38
+ }
43
39
 
44
40
  err = uv__socket(domain, SOCK_STREAM, 0);
45
41
  if (err < 0)
@@ -56,6 +52,40 @@ static int maybe_new_socket(uv_tcp_t* handle, int domain, int flags) {
56
52
  }
57
53
 
58
54
 
55
+ int uv_tcp_init_ex(uv_loop_t* loop, uv_tcp_t* tcp, unsigned int flags) {
56
+ int domain;
57
+
58
+ /* Use the lower 8 bits for the domain */
59
+ domain = flags & 0xFF;
60
+ if (domain != AF_INET && domain != AF_INET6 && domain != AF_UNSPEC)
61
+ return -EINVAL;
62
+
63
+ if (flags & ~0xFF)
64
+ return -EINVAL;
65
+
66
+ uv__stream_init(loop, (uv_stream_t*)tcp, UV_TCP);
67
+
68
+ /* If anything fails beyond this point we need to remove the handle from
69
+ * the handle queue, since it was added by uv__handle_init in uv_stream_init.
70
+ */
71
+
72
+ if (domain != AF_UNSPEC) {
73
+ int err = maybe_new_socket(tcp, domain, 0);
74
+ if (err) {
75
+ QUEUE_REMOVE(&tcp->handle_queue);
76
+ return err;
77
+ }
78
+ }
79
+
80
+ return 0;
81
+ }
82
+
83
+
84
+ int uv_tcp_init(uv_loop_t* loop, uv_tcp_t* tcp) {
85
+ return uv_tcp_init_ex(loop, tcp, AF_UNSPEC);
86
+ }
87
+
88
+
59
89
  int uv__tcp_bind(uv_tcp_t* tcp,
60
90
  const struct sockaddr* addr,
61
91
  unsigned int addrlen,
@@ -91,8 +121,13 @@ int uv__tcp_bind(uv_tcp_t* tcp,
91
121
  #endif
92
122
 
93
123
  errno = 0;
94
- if (bind(tcp->io_watcher.fd, addr, addrlen) && errno != EADDRINUSE)
124
+ if (bind(tcp->io_watcher.fd, addr, addrlen) && errno != EADDRINUSE) {
125
+ if (errno == EAFNOSUPPORT)
126
+ /* OSX, other BSDs and SunoS fail with EAFNOSUPPORT when binding a
127
+ * socket created with AF_INET to an AF_INET6 address or vice versa. */
128
+ return -EINVAL;
95
129
  return -errno;
130
+ }
96
131
  tcp->delayed_error = -errno;
97
132
 
98
133
  if (addr->sa_family == AF_INET6)
@@ -45,7 +45,7 @@ static void* uv__thread_start(void *arg)
45
45
 
46
46
  ctx_p = arg;
47
47
  ctx = *ctx_p;
48
- free(ctx_p);
48
+ uv__free(ctx_p);
49
49
  ctx.entry(ctx.arg);
50
50
 
51
51
  return 0;
@@ -56,7 +56,7 @@ int uv_thread_create(uv_thread_t *tid, void (*entry)(void *arg), void *arg) {
56
56
  struct thread_ctx* ctx;
57
57
  int err;
58
58
 
59
- ctx = malloc(sizeof(*ctx));
59
+ ctx = uv__malloc(sizeof(*ctx));
60
60
  if (ctx == NULL)
61
61
  return UV_ENOMEM;
62
62
 
@@ -66,7 +66,7 @@ int uv_thread_create(uv_thread_t *tid, void (*entry)(void *arg), void *arg) {
66
66
  err = pthread_create(tid, NULL, uv__thread_start, ctx);
67
67
 
68
68
  if (err)
69
- free(ctx);
69
+ uv__free(ctx);
70
70
 
71
71
  return -err;
72
72
  }
@@ -124,14 +124,14 @@ void uv_mutex_lock(uv_mutex_t* mutex) {
124
124
  int uv_mutex_trylock(uv_mutex_t* mutex) {
125
125
  int err;
126
126
 
127
- /* FIXME(bnoordhuis) EAGAIN means recursive lock limit reached. Arguably
128
- * a bug, should probably abort rather than return -EAGAIN.
129
- */
130
127
  err = pthread_mutex_trylock(mutex);
131
- if (err && err != EBUSY && err != EAGAIN)
132
- abort();
128
+ if (err) {
129
+ if (err != EBUSY && err != EAGAIN)
130
+ abort();
131
+ return -EBUSY;
132
+ }
133
133
 
134
- return -err;
134
+ return 0;
135
135
  }
136
136
 
137
137
 
@@ -162,10 +162,13 @@ int uv_rwlock_tryrdlock(uv_rwlock_t* rwlock) {
162
162
  int err;
163
163
 
164
164
  err = pthread_rwlock_tryrdlock(rwlock);
165
- if (err && err != EBUSY && err != EAGAIN)
166
- abort();
165
+ if (err) {
166
+ if (err != EBUSY && err != EAGAIN)
167
+ abort();
168
+ return -EBUSY;
169
+ }
167
170
 
168
- return -err;
171
+ return 0;
169
172
  }
170
173
 
171
174
 
@@ -185,10 +188,13 @@ int uv_rwlock_trywrlock(uv_rwlock_t* rwlock) {
185
188
  int err;
186
189
 
187
190
  err = pthread_rwlock_trywrlock(rwlock);
188
- if (err && err != EBUSY && err != EAGAIN)
189
- abort();
191
+ if (err) {
192
+ if (err != EBUSY && err != EAGAIN)
193
+ abort();
194
+ return -EBUSY;
195
+ }
190
196
 
191
- return -err;
197
+ return 0;
192
198
  }
193
199
 
194
200