pipe.cc 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194
  1. /* vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
  2. *
  3. * Gearmand client and server library.
  4. *
  5. * Copyright (C) 2012 Data Differential, http://datadifferential.com/
  6. * All rights reserved.
  7. *
  8. * Redistribution and use in source and binary forms, with or without
  9. * modification, are permitted provided that the following conditions are
  10. * met:
  11. *
  12. * * Redistributions of source code must retain the above copyright
  13. * notice, this list of conditions and the following disclaimer.
  14. *
  15. * * Redistributions in binary form must reproduce the above
  16. * copyright notice, this list of conditions and the following disclaimer
  17. * in the documentation and/or other materials provided with the
  18. * distribution.
  19. *
  20. * * The names of its contributors may not be used to endorse or
  21. * promote products derived from this software without specific prior
  22. * written permission.
  23. *
  24. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  25. * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  26. * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  27. * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  28. * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  29. * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  30. * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  31. * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  32. * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  33. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  34. * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  35. *
  36. */
  37. #include "gear_config.h"
  38. #include "libgearman/pipe.h"
  39. #include "libgearman/common.h"
  40. #include "libgearman/assert.hpp"
  41. #include <cerrno>
  42. #include <cstdio>
  43. #include <cstring>
  44. #include <fcntl.h>
  45. #include <unistd.h>
  46. #ifndef FD_CLOEXEC
  47. # define FD_CLOEXEC 0
  48. #endif
  49. // This is not called if HAVE_PIPE2 is true
  50. static inline bool set_cloexec(int pipedes_[2], const size_t x)
  51. {
  52. if (FD_CLOEXEC)
  53. {
  54. int flags;
  55. do
  56. {
  57. flags= fcntl(pipedes_[x], F_GETFD, 0);
  58. } while (flags == -1 and (errno == EINTR or errno == EAGAIN));
  59. if (flags != -1)
  60. {
  61. int retval;
  62. do
  63. {
  64. retval= fcntl (pipedes_[x], F_SETFD, flags | FD_CLOEXEC);
  65. } while (retval == -1 && (errno == EINTR or errno == EAGAIN));
  66. if (retval != -1)
  67. {
  68. return true;
  69. }
  70. #if defined(DEBUG) && DEBUG
  71. perror("fcntl(pipedes_[x], F_GETFD, 0)");
  72. #endif
  73. return false;
  74. }
  75. #if defined(DEBUG) && DEBUG
  76. perror("fcntl (pipedes_[x], F_SETFD, FD_CLOEXEC)");
  77. #endif
  78. }
  79. return false;
  80. }
  81. // This is not called if HAVE_PIPE2 is true
  82. static inline bool set_nonblock(int pipedes_[2], const size_t x)
  83. {
  84. int flags;
  85. do
  86. {
  87. flags= fcntl(pipedes_[x], F_GETFL, 0);
  88. } while (flags == -1 and (errno == EINTR or errno == EAGAIN));
  89. if (flags != -1)
  90. {
  91. int retval;
  92. do
  93. {
  94. retval= fcntl(pipedes_[x], F_SETFL, flags | O_NONBLOCK);
  95. } while (retval == -1 and (errno == EINTR or errno == EAGAIN));
  96. if (retval != -1)
  97. {
  98. return true;
  99. }
  100. #if defined(DEBUG) && DEBUG
  101. perror("fcntl(pipedes_[x], F_SETFL, flags | O_NONBLOCK)");
  102. #endif
  103. }
  104. #if defined(DEBUG) && DEBUG
  105. perror("fcntl(pipedes_[x], F_GETFL, 0)");
  106. #endif
  107. return false;
  108. }
  109. bool setup_shutdown_pipe(int pipedes_[2])
  110. {
  111. #if defined(HAVE_PIPE2) && HAVE_PIPE2
  112. if (pipe2(pipedes_, O_NONBLOCK|O_CLOEXEC) == -1)
  113. {
  114. #if defined(DEBUG) && DEBUG
  115. perror("pipe2(pipedes_, O_NONBLOCK|O_CLOEXEC)");
  116. #endif
  117. return false;
  118. }
  119. #else
  120. if (pipe(pipedes_) == -1)
  121. {
  122. #if defined(DEBUG) && DEBUG
  123. perror("pipe()");
  124. #endif
  125. return false;
  126. }
  127. #endif
  128. for (size_t x= 0; x < 2; ++x)
  129. {
  130. bool success= true;
  131. #ifdef F_SETNOSIGPIPE
  132. if (F_SETNOSIGPIPE)
  133. {
  134. int fcntl_sig_error;
  135. do
  136. {
  137. fcntl_sig_error= fcntl(pipedes_[x], F_SETNOSIGPIPE, 0);
  138. } while (fcntl_sig_error == -1 and (errno == EINTR or errno == EAGAIN));
  139. if (fcntl_sig_error == -1)
  140. {
  141. #if defined(DEBUG) && DEBUG
  142. perror ("fcntl_sig_error= fcntl(pipedes_[x], F_SETNOSIGPIPE, 0)");
  143. #endif
  144. success= false;
  145. }
  146. }
  147. #endif // F_SETNOSIGPIPE
  148. #if defined(HAVE_PIPE2)
  149. if (HAVE_PIPE2)
  150. { }
  151. else
  152. #endif // defined(HAVE_PIPE2)
  153. {
  154. if ((success= set_cloexec(pipedes_, x)))
  155. {
  156. success= set_nonblock(pipedes_, x);
  157. }
  158. }
  159. if (success == false)
  160. {
  161. if (errno != EBADF)
  162. {
  163. close(pipedes_[0]);
  164. close(pipedes_[1]);
  165. }
  166. return false;
  167. }
  168. }
  169. return true;
  170. }