"Fossies" - the Fresh Open Source Software Archive

Member "minidlna-1.3.0/process.c" (24 Nov 2020, 4619 Bytes) of package /linux/privat/minidlna-1.3.0.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "process.c" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 1.2.1_vs_1.3.0.

    1 /* Process handling
    2  *
    3  * Copyright © 2006, Thomas Bernard
    4  * Copyright © 2013, Benoît Knecht <benoit.knecht@fsfe.org>
    5  *
    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 met:
   10  *     * Redistributions of source code must retain the above copyright
   11  *       notice, this list of conditions and the following disclaimer.
   12  *     * Redistributions in binary form must reproduce the above copyright
   13  *       notice, this list of conditions and the following disclaimer in the
   14  *       documentation and/or other materials provided with the distribution.
   15  *     * The name of the author may not be used to endorse or promote products
   16  *       derived from this software without specific prior written permission.
   17  *
   18  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
   19  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   20  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   21  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
   22  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
   23  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
   24  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   25  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
   26  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   27  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   28  * POSSIBILITY OF SUCH DAMAGE.
   29  */
   30 #include <sys/types.h>
   31 #include <sys/stat.h>
   32 #include <unistd.h>
   33 #include <fcntl.h>
   34 #include <stdio.h>
   35 #include <stdlib.h>
   36 #include <errno.h>
   37 #include <string.h>
   38 #include <signal.h>
   39 #include <sys/wait.h>
   40 
   41 #include "config.h"
   42 #include "event.h"
   43 #include "upnpglobalvars.h"
   44 #include "process.h"
   45 #include "log.h"
   46 
   47 struct child *children = NULL;
   48 int number_of_children = 0;
   49 
   50 static void
   51 add_process_info(pid_t pid, struct client_cache_s *client)
   52 {
   53     struct child *child;
   54     int i;
   55 
   56     for (i = 0; i < runtime_vars.max_connections; i++)
   57     {
   58         child = children+i;
   59         if (child->pid)
   60             continue;
   61         child->pid = pid;
   62         child->client = client;
   63         child->age = time(NULL);
   64         break;
   65     }
   66 }
   67 
   68 static inline void
   69 remove_process_info(pid_t pid)
   70 {
   71     struct child *child;
   72     int i;
   73 
   74     for (i = 0; i < runtime_vars.max_connections; i++)
   75     {
   76         child = children+i;
   77         if (child->pid != pid)
   78             continue;
   79         child->pid = 0;
   80         if (child->client)
   81             child->client->connections--;
   82         break;
   83     }
   84 }
   85 
   86 pid_t
   87 process_fork(struct client_cache_s *client)
   88 {
   89     if (number_of_children >= runtime_vars.max_connections)
   90     {
   91         DPRINTF(E_WARN, L_GENERAL, "Exceeded max connections [%d], not forking\n",
   92             runtime_vars.max_connections);
   93         errno = EAGAIN;
   94         return -1;
   95     }
   96 
   97     pid_t pid = fork();
   98     if (pid > 0)
   99     {
  100         if (client)
  101             client->connections++;
  102         add_process_info(pid, client);
  103         number_of_children++;
  104     } else if (pid == 0)
  105         event_module.fini();
  106     else
  107         DPRINTF(E_FATAL, L_GENERAL, "Fork() failed: %s\n", strerror(errno));
  108 
  109     return pid;
  110 }
  111 
  112 void
  113 process_handle_child_termination(int signal)
  114 {
  115     pid_t pid;
  116 
  117     while ((pid = waitpid(-1, NULL, WNOHANG)))
  118     {
  119         if (pid == -1)
  120         {
  121             if (errno == EINTR)
  122                 continue;
  123             else
  124                 break;
  125         }
  126         number_of_children--;
  127         remove_process_info(pid);
  128     }
  129 }
  130 
  131 int
  132 process_daemonize(void)
  133 {
  134     int pid;
  135 #ifndef USE_DAEMON
  136     int i;
  137 
  138     switch(fork())
  139     {
  140         /* fork error */
  141         case -1:
  142             perror("fork()");
  143             exit(1);
  144 
  145         /* child process */
  146         case 0:
  147         /* obtain a new process group */
  148             if( (pid = setsid()) < 0)
  149             {
  150                 perror("setsid()");
  151                 exit(1);
  152             }
  153 
  154             /* close all descriptors */
  155             for (i=getdtablesize();i>=0;--i) close(i);      
  156 
  157             i = open("/dev/null",O_RDWR); /* open stdin */
  158             dup(i); /* stdout */
  159             dup(i); /* stderr */
  160 
  161             umask(027);
  162             chdir("/");
  163 
  164             break;
  165         /* parent process */
  166         default:
  167             exit(0);
  168     }
  169 #else
  170     if( daemon(0, 0) < 0 )
  171         perror("daemon()");
  172     pid = getpid();
  173 #endif
  174     return pid;
  175 }
  176 
  177 int
  178 process_check_if_running(const char *fname)
  179 {
  180     char buffer[64];
  181     int pidfile;
  182     pid_t pid;
  183 
  184     if(!fname || *fname == '\0')
  185         return -1;
  186 
  187     if( (pidfile = open(fname, O_RDONLY)) < 0)
  188         return 0;
  189 
  190     memset(buffer, 0, 64);
  191 
  192     if(read(pidfile, buffer, 63) > 0)
  193     {
  194         if( (pid = atol(buffer)) > 0)
  195         {
  196             if(!kill(pid, 0))
  197             {
  198                 close(pidfile);
  199                 return -2;
  200             }
  201         }
  202     }
  203 
  204     close(pidfile);
  205 
  206     return 0;
  207 }
  208 
  209 void
  210 process_reap_children(void)
  211 {
  212     struct child *child;
  213     int i;
  214 
  215     for (i = 0; i < runtime_vars.max_connections; i++)
  216     {
  217         child = children+i;
  218         if (child->pid)
  219             kill(child->pid, SIGKILL);
  220     }
  221 }