1 /* Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements. See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache License, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include "apr.h"
18 #include "apr_poll.h"
19 #include "apr_time.h"
20 #include "apr_portable.h"
21 #include "apr_arch_file_io.h"
22 #include "apr_arch_networkio.h"
23 #include "apr_arch_poll_private.h"
24 #include "apr_arch_inherit.h"
25
26 #if !APR_FILES_AS_SOCKETS
27
28 #ifdef WIN32
29
apr_poll_create_wakeup_pipe(apr_pool_t * pool,apr_pollfd_t * pfd,apr_file_t ** wakeup_pipe)30 apr_status_t apr_poll_create_wakeup_pipe(apr_pool_t *pool, apr_pollfd_t *pfd,
31 apr_file_t **wakeup_pipe)
32 {
33 apr_status_t rv;
34
35 if ((rv = apr_file_socket_pipe_create(&wakeup_pipe[0], &wakeup_pipe[1],
36 pool)) != APR_SUCCESS)
37 return rv;
38
39 pfd->reqevents = APR_POLLIN;
40 pfd->desc_type = APR_POLL_FILE;
41 pfd->desc.f = wakeup_pipe[0];
42 return APR_SUCCESS;
43 }
44
apr_poll_close_wakeup_pipe(apr_file_t ** wakeup_pipe)45 apr_status_t apr_poll_close_wakeup_pipe(apr_file_t **wakeup_pipe)
46 {
47 apr_status_t rv0 = APR_SUCCESS;
48 apr_status_t rv1 = APR_SUCCESS;
49
50 /* Close both sides of the wakeup pipe */
51 if (wakeup_pipe[0]) {
52 rv0 = apr_file_socket_pipe_close(wakeup_pipe[0]);
53 wakeup_pipe[0] = NULL;
54 }
55 if (wakeup_pipe[1]) {
56 rv1 = apr_file_socket_pipe_close(wakeup_pipe[1]);
57 wakeup_pipe[1] = NULL;
58 }
59 return rv0 ? rv0 : rv1;
60 }
61
62 #else /* !WIN32 */
63
apr_poll_create_wakeup_pipe(apr_pollfd_t * pfd,apr_file_t ** wakeup_pipe)64 apr_status_t apr_poll_create_wakeup_pipe(apr_pollfd_t *pfd, apr_file_t **wakeup_pipe)
65 {
66 return APR_ENOTIMPL;
67 }
68
apr_poll_close_wakeup_pipe(apr_file_t ** wakeup_pipe)69 apr_status_t apr_poll_close_wakeup_pipe(apr_file_t **wakeup_pipe)
70 {
71 return APR_ENOTIMPL;
72 }
73
74 #endif /* !WIN32 */
75
76 #else /* APR_FILES_AS_SOCKETS */
77
apr_poll_create_wakeup_pipe(apr_pool_t * pool,apr_pollfd_t * pfd,apr_file_t ** wakeup_pipe)78 apr_status_t apr_poll_create_wakeup_pipe(apr_pool_t *pool, apr_pollfd_t *pfd,
79 apr_file_t **wakeup_pipe)
80 {
81 apr_status_t rv;
82
83 if ((rv = apr_file_pipe_create(&wakeup_pipe[0], &wakeup_pipe[1],
84 pool)) != APR_SUCCESS)
85 return rv;
86
87 pfd->p = pool;
88 pfd->reqevents = APR_POLLIN;
89 pfd->desc_type = APR_POLL_FILE;
90 pfd->desc.f = wakeup_pipe[0];
91
92 {
93 int flags;
94
95 if ((flags = fcntl(wakeup_pipe[0]->filedes, F_GETFD)) == -1)
96 return errno;
97
98 flags |= FD_CLOEXEC;
99 if (fcntl(wakeup_pipe[0]->filedes, F_SETFD, flags) == -1)
100 return errno;
101 }
102 {
103 int flags;
104
105 if ((flags = fcntl(wakeup_pipe[1]->filedes, F_GETFD)) == -1)
106 return errno;
107
108 flags |= FD_CLOEXEC;
109 if (fcntl(wakeup_pipe[1]->filedes, F_SETFD, flags) == -1)
110 return errno;
111 }
112
113 return APR_SUCCESS;
114 }
115
apr_poll_close_wakeup_pipe(apr_file_t ** wakeup_pipe)116 apr_status_t apr_poll_close_wakeup_pipe(apr_file_t **wakeup_pipe)
117 {
118 apr_status_t rv0 = APR_SUCCESS;
119 apr_status_t rv1 = APR_SUCCESS;
120
121 /* Close both sides of the wakeup pipe */
122 if (wakeup_pipe[0]) {
123 rv0 = apr_file_close(wakeup_pipe[0]);
124 wakeup_pipe[0] = NULL;
125 }
126 if (wakeup_pipe[1]) {
127 rv1 = apr_file_close(wakeup_pipe[1]);
128 wakeup_pipe[1] = NULL;
129 }
130 return rv0 ? rv0 : rv1;
131 }
132
133 #endif /* APR_FILES_AS_SOCKETS */
134
135 /* Read and discard whatever is in the wakeup pipe.
136 */
apr_poll_drain_wakeup_pipe(apr_file_t ** wakeup_pipe)137 void apr_poll_drain_wakeup_pipe(apr_file_t **wakeup_pipe)
138 {
139 char rb[512];
140 apr_size_t nr = sizeof(rb);
141
142 while (apr_file_read(wakeup_pipe[0], rb, &nr) == APR_SUCCESS) {
143 /* Although we write just one byte to the other end of the pipe
144 * during wakeup, multiple threads could call the wakeup.
145 * So simply drain out from the input side of the pipe all
146 * the data.
147 */
148 if (nr != sizeof(rb))
149 break;
150 }
151 }
152