(file) Return to Socket.c CVS log (file) (dir) Up to [Pegasus] / pegasus / src / Executor

  1 kumpf 1.2 /*
  2 martin 1.5 //%LICENSE////////////////////////////////////////////////////////////////
  3 martin 1.6 //
  4 martin 1.5 // Licensed to The Open Group (TOG) under one or more contributor license
  5            // agreements.  Refer to the OpenPegasusNOTICE.txt file distributed with
  6            // this work for additional information regarding copyright ownership.
  7            // Each contributor licenses this file to you under the OpenPegasus Open
  8            // Source License; you may not use this file except in compliance with the
  9            // License.
 10 martin 1.6 //
 11 martin 1.5 // Permission is hereby granted, free of charge, to any person obtaining a
 12            // copy of this software and associated documentation files (the "Software"),
 13            // to deal in the Software without restriction, including without limitation
 14            // the rights to use, copy, modify, merge, publish, distribute, sublicense,
 15            // and/or sell copies of the Software, and to permit persons to whom the
 16            // Software is furnished to do so, subject to the following conditions:
 17 martin 1.6 //
 18 martin 1.5 // The above copyright notice and this permission notice shall be included
 19            // in all copies or substantial portions of the Software.
 20 martin 1.6 //
 21 martin 1.5 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
 22 martin 1.6 // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 23 martin 1.5 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
 24            // IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
 25            // CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
 26            // TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
 27            // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 28 martin 1.6 //
 29 martin 1.5 //////////////////////////////////////////////////////////////////////////
 30 kumpf  1.2 */
 31 martin 1.5 
 32 kumpf  1.2 #include "Socket.h"
 33            #include <unistd.h>
 34            #include <fcntl.h>
 35            #include <signal.h>
 36            #include <string.h>
 37            #include <errno.h>
 38            #include <sys/socket.h>
 39            #include "Exit.h"
 40            #include "Globals.h"
 41            #include "Defines.h"
 42            #include "Socket.h"
 43            
 44            /*
 45            **==============================================================================
 46            **
 47            ** CloseOnExec()
 48            **
 49            **     Direct the kernel not to keep the given file descriptor open across
 50            **     exec() system call.
 51            **
 52            **==============================================================================
 53 kumpf  1.2 */
 54            
 55            int CloseOnExec(int fd)
 56            {
 57                return fcntl(fd, F_SETFD, fcntl(fd, F_GETFD) | FD_CLOEXEC);
 58            }
 59            
 60            /*
 61            **==============================================================================
 62            **
 63            ** SetNonBlocking()
 64            **
 65            **     Set the given socket into non-blocking mode.
 66            **
 67            **==============================================================================
 68            */
 69            
 70            int SetNonBlocking(int sock)
 71            {
 72                return fcntl(sock, F_SETFL, fcntl(sock, F_GETFL, 0) | O_NONBLOCK);
 73            }
 74 kumpf  1.2 
 75            /*
 76            **==============================================================================
 77            **
 78            ** SetBlocking()
 79            **
 80            **     Set the given socket into blocking mode.
 81            **
 82            **==============================================================================
 83            */
 84            
 85            int SetBlocking(int sock)
 86            {
 87                return fcntl(sock, F_SETFL, fcntl(sock, F_GETFL, 0) & ~O_NONBLOCK);
 88            }
 89            
 90            /*
 91            **==============================================================================
 92            **
 93 kumpf  1.3 ** WaitForReadEnable()
 94 kumpf  1.2 **
 95            **     Wait until the given socket is read-enabled. Returns 1 if read enabled
 96            **     and 0 on timed out.
 97            **
 98            **==============================================================================
 99            */
100            
101 kumpf  1.3 int WaitForReadEnable(int sock, long timeoutMsec)
102 kumpf  1.2 {
103                struct timeval timeout;
104            
105                fd_set readSet;
106                FD_ZERO(&readSet);
107                FD_SET(sock, &readSet);
108            
109                timeout.tv_sec = timeoutMsec / 1000;
110                timeout.tv_usec = (timeoutMsec % 1000) * 1000;
111            
112                return select(sock + 1, &readSet, 0, 0, &timeout);
113            }
114            
115            /*
116            **==============================================================================
117            **
118            ** _waitForWriteEnable()
119            **
120            **     Wait until the given socket is write-enabled. Returns 1 if write enabled
121            **     and 0 on timed out.
122            **
123 kumpf  1.2 **==============================================================================
124            */
125            
126            static int _waitForWriteEnable(int sock, long timeoutMsec)
127            {
128                fd_set writeSet;
129                struct timeval timeout;
130            
131                FD_ZERO(&writeSet);
132                FD_SET(sock, &writeSet);
133            
134                timeout.tv_sec = timeoutMsec / 1000;
135                timeout.tv_usec = (timeoutMsec % 1000) * 1000;
136            
137                return select(sock + 1, 0, &writeSet, 0, &timeout);
138            }
139            
140            /*
141            **==============================================================================
142            **
143            ** RecvNonBlock()
144 kumpf  1.2 **
145            **     Receive at least size bytes from the given non-blocking socket.
146            **
147            **==============================================================================
148            */
149            
150            ssize_t RecvNonBlock(
151                int sock,
152                void* buffer,
153                size_t size)
154            {
155                const long TIMEOUT_MSEC = 250;
156                size_t r = size;
157                char* p = (char*)buffer;
158            
159                if (size == 0)
160                    return -1;
161            
162                while (r)
163                {
164 kumpf  1.3         int status = WaitForReadEnable(sock, TIMEOUT_MSEC);
165 kumpf  1.2         ssize_t n;
166            
167                    if ((globals.signalMask & (1 << SIGTERM)) ||
168                        (globals.signalMask & (1 << SIGINT)))
169                    {
170                        /* Exit on either of these signals. */
171                        Exit(0);
172                    }
173            
174                    if (status == 0)
175                        continue;
176            
177                    EXECUTOR_RESTART(read(sock, p, r), n);
178            
179                    if (n == -1 && errno == EINTR)
180                        continue;
181            
182                    if (n == -1)
183                    {
184                        if (errno == EWOULDBLOCK)
185                        {
186 kumpf  1.2                 size_t total = size - r;
187            
188                            if (total)
189                                return total;
190            
191                            return -1;
192                        }
193                        else
194                            return -1;
195                    }
196                    else if (n == 0)
197                        return size - r;
198            
199                    r -= n;
200                    p += n;
201                }
202            
203                return size - r;
204            }
205            
206            /*
207 kumpf  1.2 **==============================================================================
208            **
209            ** SendNonBlock()
210            **
211            **     Sends at least size bytes on the given non-blocking socket.
212            **
213            **==============================================================================
214            */
215            
216            ssize_t SendNonBlock(
217                int sock,
218                const void* buffer,
219                size_t size)
220            {
221                const long TIMEOUT_MSEC = 250;
222                size_t r = size;
223                char* p = (char*)buffer;
224            
225                while (r)
226                {
227                    int status = _waitForWriteEnable(sock, TIMEOUT_MSEC);
228 kumpf  1.2         ssize_t n;
229            
230                    if ((globals.signalMask & (1 << SIGTERM)) ||
231                        (globals.signalMask & (1 << SIGINT)))
232                    {
233                        /* Exit on either of these signals. */
234                        Exit(0);
235                    }
236            
237                    if (status == 0)
238                        continue;
239            
240                    EXECUTOR_RESTART(write(sock, p, r), n);
241            
242                    if (n == -1)
243                    {
244                        if (errno == EWOULDBLOCK)
245                            return size - r;
246                        else
247                            return -1;
248                    }
249 kumpf  1.2         else if (n == 0)
250                        return size - r;
251            
252                    r -= n;
253                    p += n;
254                }
255            
256                return size - r;
257            }
258            
259            /*
260            **==============================================================================
261            **
262            ** SendDescriptorArray()
263            **
264            **     Send an array of descriptors (file, socket, pipe) to the child process.
265            **
266            **==============================================================================
267            */
268            
269            ssize_t SendDescriptorArray(int sock, int descriptors[], size_t count)
270 kumpf  1.2 {
271                struct iovec iov[1];
272                char dummy;
273                struct msghdr mh;
274                int result;
275            #if defined(HAVE_MSG_CONTROL)
276                size_t size;
277                char* data;
278                struct cmsghdr* cmh;
279            
280                /* Allocate space for control header plus descriptors. */
281            
282                size = CMSG_SPACE(sizeof(int) * count);
283                data = (char*)malloc(size);
284 kumpf  1.4     memset(data, 0, size);
285 kumpf  1.2 
286                /* Initialize msghdr struct to refer to control data. */
287            
288                memset(&mh, 0, sizeof(mh));
289                mh.msg_control = data;
290                mh.msg_controllen = size;
291            
292                /* Fill in the control data struct with the descriptor and other fields. */
293            
294                cmh = CMSG_FIRSTHDR(&mh);
295                cmh->cmsg_len = CMSG_LEN(sizeof(int) * count);
296                cmh->cmsg_level = SOL_SOCKET;
297                cmh->cmsg_type = SCM_RIGHTS;
298                memcpy((int*)CMSG_DATA(cmh), descriptors, sizeof(int) * count);
299            
300            #else /* defined(HAVE_MSG_CONTROL) */
301            
302                memset(&mh, 0, sizeof(mh));
303                mh.msg_accrights = (caddr_t)descriptors;
304                mh.msg_accrightslen = count * sizeof(int);
305            
306 kumpf  1.2 #endif /* defined(HAVE_MSG_CONTROL) */
307            
308                /*
309                 * Prepare to send single dummy byte. It will not be used but we must send
310                 * at least one byte otherwise the call will fail on some platforms.
311                 */
312            
313                memset(iov, 0, sizeof(iov));
314                dummy = '\0';
315                iov[0].iov_base = &dummy;
316                iov[0].iov_len = 1;
317                mh.msg_iov = iov;
318                mh.msg_iovlen = 1;
319            
320                /* Send message to child. */
321            
322                result = sendmsg(sock, &mh, 0);
323            
324            #if defined(HAVE_MSG_CONTROL)
325                free(data);
326            #endif
327 kumpf  1.2 
328                return result == -1 ? -1 : 0;
329            }
330            
331            /*
332            **==============================================================================
333            **
334            ** CreateSocketPair()
335            **
336            **     Send an array of descriptors (file, socket, pipe) to the child process.
337            **
338            **==============================================================================
339            */
340            
341            int CreateSocketPair(int pair[2])
342            {
343                return socketpair(AF_UNIX, SOCK_STREAM, 0, pair);
344            }

No CVS admin address has been configured
Powered by
ViewCVS 0.9.2