]>
Commit | Line | Data |
---|---|---|
f740a279 | 1 | |
429fdbec | 2 | /* |
cc192b50 | 3 | * $Id: unlinkd.cc,v 1.65 2007/12/14 23:11:48 amosjeffries Exp $ |
429fdbec | 4 | * |
99cce4cb | 5 | * DEBUG: section 2 Unlink Daemon |
429fdbec | 6 | * AUTHOR: Duane Wessels |
7 | * | |
2b6662ba | 8 | * SQUID Web Proxy Cache http://www.squid-cache.org/ |
e25c139f | 9 | * ---------------------------------------------------------- |
429fdbec | 10 | * |
2b6662ba | 11 | * Squid is the result of efforts by numerous individuals from |
12 | * the Internet community; see the CONTRIBUTORS file for full | |
13 | * details. Many organizations have provided support for Squid's | |
14 | * development; see the SPONSORS file for full details. Squid is | |
15 | * Copyrighted (C) 2001 by the Regents of the University of | |
16 | * California; see the COPYRIGHT file for full details. Squid | |
17 | * incorporates software developed and/or copyrighted by other | |
18 | * sources; see the CREDITS file for full details. | |
429fdbec | 19 | * |
20 | * This program is free software; you can redistribute it and/or modify | |
21 | * it under the terms of the GNU General Public License as published by | |
22 | * the Free Software Foundation; either version 2 of the License, or | |
23 | * (at your option) any later version. | |
24 | * | |
25 | * This program is distributed in the hope that it will be useful, | |
26 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
27 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
28 | * GNU General Public License for more details. | |
29 | * | |
30 | * You should have received a copy of the GNU General Public License | |
31 | * along with this program; if not, write to the Free Software | |
cbdec147 | 32 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA. |
e25c139f | 33 | * |
429fdbec | 34 | */ |
35 | ||
6b8e7481 | 36 | #include "squid.h" |
5c3c8c03 | 37 | #include "SquidTime.h" |
528b2c61 | 38 | #include "fde.h" |
9ece7c7c | 39 | #include "xusleep.h" |
528b2c61 | 40 | |
429fdbec | 41 | /* This code gets linked to Squid */ |
42 | ||
06f8f350 | 43 | static int unlinkd_wfd = -1; |
44 | static int unlinkd_rfd = -1; | |
429fdbec | 45 | |
b5d712b5 | 46 | static void * hIpc; |
5c3c8c03 | 47 | static pid_t pid; |
48 | ||
9bc73deb | 49 | #define UNLINKD_QUEUE_LIMIT 20 |
50 | ||
429fdbec | 51 | void |
52 | unlinkdUnlink(const char *path) | |
53 | { | |
9bc73deb | 54 | char buf[MAXPATHLEN]; |
429fdbec | 55 | int l; |
9bc73deb | 56 | int x; |
57 | static int queuelen = 0; | |
62e76326 | 58 | |
06f8f350 | 59 | if (unlinkd_wfd < 0) { |
62e76326 | 60 | debug_trap("unlinkdUnlink: unlinkd_wfd < 0"); |
61 | safeunlink(path, 0); | |
62 | return; | |
429fdbec | 63 | } |
62e76326 | 64 | |
9bc73deb | 65 | /* |
9ece7c7c | 66 | * If the queue length is greater than our limit, then we pause |
67 | * for a small amount of time, hoping that unlinkd has some | |
68 | * feedback for us. Maybe it just needs a slice of the CPU's | |
69 | * time. | |
70 | */ | |
9bc73deb | 71 | if (queuelen >= UNLINKD_QUEUE_LIMIT) { |
9ece7c7c | 72 | #if defined(USE_EPOLL) || defined(USE_KQUEUE) |
73 | /* | |
74 | * DPW 2007-04-23 | |
75 | * We can't use fd_set when using epoll() or kqueue(). In | |
76 | * these cases we block for 10 ms. | |
77 | */ | |
78 | xusleep(10000); | |
79 | #else | |
80 | /* | |
81 | * DPW 2007-04-23 | |
82 | * When we can use select, block for up to 100 ms. | |
83 | */ | |
e7a67ff1 | 84 | struct timeval to; |
85 | fd_set R; | |
86 | FD_ZERO(&R); | |
87 | FD_SET(unlinkd_rfd, &R); | |
88 | to.tv_sec = 0; | |
89 | to.tv_usec = 100000; | |
90 | select(unlinkd_rfd + 1, &R, NULL, NULL, &to); | |
9ece7c7c | 91 | #endif |
9bc73deb | 92 | } |
62e76326 | 93 | |
9bc73deb | 94 | /* |
62e76326 | 95 | * If there is at least one outstanding unlink request, then |
96 | * try to read a response. If there's nothing to read we'll | |
97 | * get an EWOULDBLOCK or whatever. If we get a response, then | |
98 | * decrement the queue size by the number of newlines read. | |
99 | */ | |
9bc73deb | 100 | if (queuelen > 0) { |
62e76326 | 101 | int x; |
102 | int i; | |
103 | char rbuf[512]; | |
104 | x = read(unlinkd_rfd, rbuf, 511); | |
105 | ||
106 | if (x > 0) { | |
107 | rbuf[x] = '\0'; | |
108 | ||
109 | for (i = 0; i < x; i++) | |
110 | if ('\n' == rbuf[i]) | |
111 | queuelen--; | |
112 | ||
113 | assert(queuelen >= 0); | |
114 | } | |
9bc73deb | 115 | } |
62e76326 | 116 | |
9bc73deb | 117 | l = strlen(path); |
118 | assert(l < MAXPATHLEN); | |
119 | xstrncpy(buf, path, MAXPATHLEN); | |
120 | buf[l++] = '\n'; | |
121 | x = write(unlinkd_wfd, buf, l); | |
62e76326 | 122 | |
9bc73deb | 123 | if (x < 0) { |
bf8fe701 | 124 | debugs(2, 1, "unlinkdUnlink: write FD " << unlinkd_wfd << " failed: " << xstrerror()); |
62e76326 | 125 | safeunlink(path, 0); |
126 | return; | |
9bc73deb | 127 | } else if (x != l) { |
bf8fe701 | 128 | debugs(2, 1, "unlinkdUnlink: FD " << unlinkd_wfd << " only wrote " << x << " of " << l << " bytes"); |
62e76326 | 129 | safeunlink(path, 0); |
130 | return; | |
9bc73deb | 131 | } |
62e76326 | 132 | |
83704487 | 133 | statCounter.unlink.requests++; |
5f0c8452 | 134 | /* |
62e76326 | 135 | * Increment this syscalls counter here, even though the syscall |
136 | * is executed by the helper process. We try to be consistent | |
137 | * in counting unlink operations. | |
138 | */ | |
3077778c | 139 | statCounter.syscalls.disk.unlinks++; |
9bc73deb | 140 | queuelen++; |
429fdbec | 141 | } |
142 | ||
143 | void | |
144 | unlinkdClose(void) | |
5c3c8c03 | 145 | #ifdef _SQUID_MSWIN_ |
146 | { | |
147 | ||
148 | if (unlinkd_wfd > -1) | |
149 | { | |
150 | debugs(2, 1, "Closing unlinkd pipe on FD " << unlinkd_wfd); | |
151 | shutdown(unlinkd_wfd, SD_BOTH); | |
152 | comm_close(unlinkd_wfd); | |
153 | ||
154 | if (unlinkd_wfd != unlinkd_rfd) | |
155 | comm_close(unlinkd_rfd); | |
156 | ||
157 | unlinkd_wfd = -1; | |
158 | ||
159 | unlinkd_rfd = -1; | |
160 | } else | |
161 | debugs(2, 0, "unlinkdClose: WARNING: unlinkd_wfd is " << unlinkd_wfd); | |
162 | ||
163 | if (hIpc) | |
164 | { | |
165 | if (WaitForSingleObject(hIpc, 5000) != WAIT_OBJECT_0) { | |
166 | getCurrentTime(); | |
167 | debugs(2, 1, "unlinkdClose: WARNING: (unlinkd," << pid << "d) didn't exit in 5 seconds"); | |
168 | } | |
169 | ||
170 | CloseHandle(hIpc); | |
171 | } | |
172 | } | |
173 | #else | |
429fdbec | 174 | { |
5c3c8c03 | 175 | |
3502d32f | 176 | if (unlinkd_wfd < 0) |
62e76326 | 177 | return; |
178 | ||
5c3c8c03 | 179 | debugs(2, 1, "Closing unlinkd pipe on FD " << unlinkd_wfd); |
62e76326 | 180 | |
06f8f350 | 181 | file_close(unlinkd_wfd); |
62e76326 | 182 | |
18e72ae1 | 183 | if (unlinkd_wfd != unlinkd_rfd) |
62e76326 | 184 | file_close(unlinkd_rfd); |
185 | ||
06f8f350 | 186 | unlinkd_wfd = -1; |
62e76326 | 187 | |
06f8f350 | 188 | unlinkd_rfd = -1; |
429fdbec | 189 | } |
190 | ||
5c3c8c03 | 191 | #endif |
192 | ||
429fdbec | 193 | void |
194 | unlinkdInit(void) | |
195 | { | |
a2c963ae | 196 | const char *args[2]; |
cc192b50 | 197 | IPAddress localhost; |
62e76326 | 198 | |
06f8f350 | 199 | args[0] = "(unlinkd)"; |
200 | args[1] = NULL; | |
cc192b50 | 201 | localhost.SetLocalhost(); |
202 | ||
b5d712b5 | 203 | pid = ipcCreate( |
1b3db6d9 | 204 | #if USE_POLL && defined(_SQUID_OSF_) |
b5d712b5 | 205 | /* pipes and poll() don't get along on DUNIX -DW */ |
206 | IPC_STREAM, | |
207 | #elif defined(_SQUID_MSWIN_) | |
208 | /* select() will fail on a pipe */ | |
209 | IPC_TCP_SOCKET, | |
2b9a692c | 210 | #else |
62e76326 | 211 | /* We currently need to use FIFO.. see below */ |
b5d712b5 | 212 | IPC_FIFO, |
2b9a692c | 213 | #endif |
b5d712b5 | 214 | Config.Program.unlinkd, |
215 | args, | |
216 | "unlinkd", | |
cc192b50 | 217 | localhost, |
b5d712b5 | 218 | &unlinkd_rfd, |
219 | &unlinkd_wfd, | |
220 | &hIpc); | |
62e76326 | 221 | |
5c3c8c03 | 222 | if (pid < 0) |
62e76326 | 223 | fatal("Failed to create unlinkd subprocess"); |
b5d712b5 | 224 | |
9ece7c7c | 225 | xusleep(250000); |
b5d712b5 | 226 | |
06f8f350 | 227 | fd_note(unlinkd_wfd, "squid -> unlinkd"); |
b5d712b5 | 228 | |
06f8f350 | 229 | fd_note(unlinkd_rfd, "unlinkd -> squid"); |
b5d712b5 | 230 | |
06f8f350 | 231 | commSetTimeout(unlinkd_rfd, -1, NULL, NULL); |
b5d712b5 | 232 | |
06f8f350 | 233 | commSetTimeout(unlinkd_wfd, -1, NULL, NULL); |
b5d712b5 | 234 | |
9bc73deb | 235 | /* |
62e76326 | 236 | * unlinkd_rfd should already be non-blocking because of |
237 | * ipcCreate. We change unlinkd_wfd to blocking mode because | |
238 | * we never want to lose an unlink request, and we don't have | |
239 | * code to retry if we get EWOULDBLOCK. Unfortunately, we can | |
240 | * do this only for the IPC_FIFO case. | |
241 | */ | |
7e3ce7b9 | 242 | assert(fd_table[unlinkd_rfd].flags.nonblocking); |
b5d712b5 | 243 | |
7e3ce7b9 | 244 | if (FD_PIPE == fd_table[unlinkd_wfd].type) |
62e76326 | 245 | commUnsetNonBlocking(unlinkd_wfd); |
b5d712b5 | 246 | |
bf8fe701 | 247 | debugs(2, 1, "Unlinkd pipe opened on FD " << unlinkd_wfd); |
5c3c8c03 | 248 | |
249 | #ifdef _SQUID_MSWIN_ | |
250 | ||
4a7a3d56 | 251 | debugs(2, 4, "Unlinkd handle: 0x" << std::hex << hIpc << std::dec << ", PID: " << pid); |
5c3c8c03 | 252 | |
253 | #endif | |
254 | ||
429fdbec | 255 | } |