⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 fatcontroller.cpp

📁 一个UNIX/LINUX下的基于内容的过滤服务器源代码
💻 CPP
📖 第 1 页 / 共 4 页
字号:
    if (rc < 0) {        ttg = true;        syslog(LOG_ERR, "%s","Error creating initial fork pool - exiting...");    }    bool preforked = true;    int tofind;    reloadconfig = false;    while (failurecount < 30 && !ttg && !reloadconfig) {                                // loop, essentially, for ever until 30                                // consecutive errors in which case something                                // is badly wrong.                                // OR, its timetogo - got a sigterm                                // OR, we need to exit to reread config        if (gentlereload) {            #ifdef DGDEBUG                cout << "gentle reload activated" << endl;            #endif            o.deleteFilterGroups();            if (!o.readFilterGroupConf()) {                reloadconfig = true;  // filter groups problem so lets                // try and reload entire config instead                // if that fails it will bomb out            }            else {                o.filter_groups_list.reset();                if (!o.readfgfile(o.filter_groups_list_location.c_str())) {                    reloadconfig = true;  // filter groups problem...                }                else {                    o.lm.garbageCollect();                    hupAllChildren();                    preFork(o.min_children);                    gentlereload = false;                }            }            flushURLCache();            continue;        }        // Lets take the opportunity to clean up our dead children if any        for(i = 0; i <= o.max_children; i++) {           pids[i].revents = 0;        }        mopUpAfterKids();        rc = poll(pids, fds, 60 * 1000);        mopUpAfterKids();        if (rc < 0) {  // was an error            #ifdef DGDEBUG                std::cout << "errno:" << errno << " " << strerror(errno) << std::endl;            #endif            if (errno == EINTR) {                continue;  // was interupted by a signal so restart            }            failurecount++;  // log the error/failure            continue;  // then continue with the looping        }        tofind = rc;        if (rc > 0) {            if ((pids[0].revents & POLLIN) > 0) {                tofind--;            }        }        if (tofind > 0) {            if (checkKidReadyStatus(tofind)) {                preforked = false;  // we are no longer waiting last prefork            }        }        freechildren = numchildren - busychildren;        #ifdef DGDEBUG            std::cout << "numchildren:" << numchildren << std::endl;            std::cout << "busychildren:" << busychildren << std::endl;            std::cout << "freechildren:" << freechildren << std::endl;            std::cout << "waitingfor:" << waitingfor << std::endl;        #endif        if (rc > 0) {            if ((pids[0].revents & (POLLERR | POLLHUP | POLLNVAL)) > 0) {                ttg = true;                syslog(LOG_ERR, "%s","Error with main listening socket.  Exiting.");                continue;            }            if ((pids[0].revents & POLLIN) > 0) {                // socket ready to accept() a connection                failurecount = 0;  // something is clearly working so reset count                if (freechildren < 1 && numchildren < o.max_children) {                    if (!preforked) {                        rc = preFork(1);                        if (rc < 0) {                            syslog(LOG_ERR, "%s","Error forking 1 extra process.");                            failurecount++;                        }                        preforked = true;                    }                    qscopy = quicksleep;  // use copy as select() can modify it                    select(0, NULL, NULL, NULL, &qscopy);  // is a very quick sleep()                    continue;                }                if (freechildren > 0) {                    tellChildAccept(getFreeChild());                }                else {                    qscopy = quicksleep;  // use copy as select() can modify it                    select(0, NULL, NULL, NULL, &qscopy);  // is a very quick sleep()                }            }        }        if (freechildren < o.minspare_children && !preforked && numchildren < o.max_children) {            rc = preFork(o.prefork_children);            preforked = true;            if (rc < 0) {                syslog(LOG_ERR, "%s","Error forking preforkchildren extra processes.");                failurecount++;            }        }        if (freechildren <= o.maxspare_children) {            time(&tmaxspare);        }        if (freechildren > o.maxspare_children) {            time(&tnow);            if ((tnow - tmaxspare) > (2 * 60)) { // 2 * 60                cullChildren(freechildren - o.maxspare_children);            }        }    }    cullChildren(numchildren); // remove the fork pool of spare children    for (int i = 0; i < o.max_children; i++) {        if (pids[i + 1].fd != -1) {            try {                close(pids[i + 1].fd);            } catch (exception& e) {}        }    }    if (numchildren > 0) {        hupAllChildren();        sleep(2); // give them a small chance to exit nicely before we force        // hmmmm I wonder if sleep() will get interupted by sigchlds?    }    if (numchildren > 0) {        killAllChildren();    }    // we might not giving enough time for defuncts to be created and then    // mopped but on exit or reload config they'll get mopped up    sleep(1);    mopUpAfterKids();    delete[] childrenpids;    delete[] childrenstates;    delete[] pids;  // 3 deletes good, memory leaks bad    if (failurecount >= 30) {        syslog(LOG_ERR, "%s","Exiting due to high failure count.");        #ifdef DGDEBUG            std::cout << "Exiting due to high failure count." << std::endl;        #endif    }    #ifdef DGDEBUG        std::cout << "Main parent process exiting." << std::endl;    #endif    serversock.close();  // be nice and neat    if (o.url_cache_number > 0) {        urllistsock.close();    }    memset(&sa, 0, sizeof(sa));    sa.sa_handler = SIG_DFL;    if (sigaction(SIGTERM, &sa, NULL)) {  // restore sig handler                                          // in child process        #ifdef DGDEBUG            std::cerr << "Error resetting signal for SIGTERM" << std::endl;        #endif        syslog(LOG_ERR, "%s","Error resetting signal for SIGTERM");    }    memset(&sa, 0, sizeof(sa));    sa.sa_handler = SIG_IGN;    if (sigaction(SIGHUP, &sa, NULL)) {  // restore sig handler                                          // in child process        #ifdef DGDEBUG            std::cerr << "Error resetting signal for SIGHUP" << std::endl;        #endif        syslog(LOG_ERR, "%s","Error resetting signal for SIGHUP");    }    memset(&sa, 0, sizeof(sa));    sa.sa_handler = SIG_IGN;    if (sigaction(SIGUSR1, &sa, NULL)) {  // restore sig handler                                          // in child process        #ifdef DGDEBUG            std::cerr << "Error resetting signal for SIGUSR1" << std::endl;        #endif        syslog(LOG_ERR, "%s","Error resetting signal for SIGUSR1");    }    memset(&sa, 0, sizeof(sa));    sa.sa_handler = SIG_DFL;    if (sigaction(SIGPIPE, &sa, NULL)) {  // restore sig handler                                          // in child process        #ifdef DGDEBUG            std::cerr << "Error resetting signal for SIGPIPE" << std::endl;        #endif        syslog(LOG_ERR, "%s","Error resetting signal for SIGPIPE");    }    if (sig_term_killall) {        struct sigaction sa, oldsa;        memset(&sa, 0, sizeof(sa)); sa.sa_handler = SIG_IGN;        sigaction(SIGTERM, &sa, &oldsa); // ignore sigterm for us        kill(0, SIGTERM);  // send everyone in this process group a TERM                           // which causes them to exit as the default action                           // but it also seems to send itself a TERM                           // so we ignore it        sigaction(SIGTERM, &oldsa, NULL); // restore prev state    }    if (reloadconfig) {        if( o.no_logger == 0 ) {            ::kill(loggerpid, SIGTERM);  // get rid of logger        }        if (o.url_cache_number > 0) {            ::kill(urllistpid, SIGTERM);  // get rid of url cache        }        return 2;    }    if (ttg) {        if( o.no_logger == 0 ) {            ::kill(loggerpid, SIGTERM);  // get rid of logger        }        if (o.url_cache_number > 0) {            ::kill(urllistpid, SIGTERM);  // get rid of url cache        }        return 0;    }    if (o.logconerror == 1) {        syslog(LOG_ERR, "%s","Main parent process exiting.");    }    return 1; // It is only possible to reach here with an error}// this is used by dansguardian.cpp, to, yep, test connection to the proxy// If report is true we log the problem.  report as false allows the caller// to test multiple times with no errorbool FatController::testProxy(std::string proxyip, int proxyport, bool report) {    int sck_inet, conn;    Socket sock;    sck_inet = sock.getFD();    if (sck_inet == -1) {        if (report) {            if (!isDaemonised) {                std::cerr << "Error creating socket to test proxy connection" << std::endl;            }            syslog(LOG_ERR, "%s","Error creating socket to test proxy connection");        }        return false;    }    conn = sock.connect(proxyip, proxyport); // hmmm, I wonder what this do    if (conn) {        if (report) {            if (!isDaemonised) {                std::cerr << "Error connecting to parent proxy" << std::endl;            }            syslog(LOG_ERR, "%s","Error connecting to parent proxy");        }        return false;    }//    close(conn);  ** delete when confirmed not needed    sock.close();    return true;  // it worked!}bool FatController::daemonise(int pidfilefd) {    if (o.no_daemon == 1) {        return true;    }    #ifdef DGDEBUG        return true;  // if debug mode is enabled we don't want to detach    #endif    if (isDaemonised) {        return true;  // we are already daemonised so this must be a                      // reload caused by a HUP    }    int nullfd = -1;    if ((nullfd = open("/dev/null", O_WRONLY, 0)) == -1) {        syslog(LOG_ERR, "%s","Couldn't open /dev/null");        return false;    }    pid_t pid;    if ((pid = fork()) < 0) {        return false;    }    else if (pid != 0) {        if (nullfd != -1) {            close(nullfd);        }        exit(0);  // parent goes bye-bye    }    // child continues    dup2(nullfd, 0);  // stdin    dup2(nullfd, 1);  // stdout    dup2(nullfd, 2); // stderr    close(nullfd);    setsid();  // become session leader    chdir("/"); // change working directory    umask(0); // clear our file mode creation mask    SysV sysv;    int rc = sysv.writePIDFile(pidfilefd);  // also closes the fd    if (rc != 0) {        syslog(LOG_ERR, "%s","Error writing to the dansguardian.pid file.");        return false;    }    isDaemonised = true;    return true;}int FatController::preFork(int num) {    if (num < waitingfor) {        return 3;  // waiting for forks already    }    #ifdef DGDEBUG        std::cout << "attempting to prefork:" << num << std::endl;    #endif    int sv[2];    pid_t  child_pid;    while(num--)  {        if (numchildren >= o.max_children) {            return 2;  // too many - geddit?        }        if(socketpair(AF_UNIX,SOCK_STREAM,0,sv) < 0)  {            return -1; // error        }        child_pid = fork();        if (child_pid == -1) {  // fork failed, for example, if the                                         // process is not allowed to create                                         // any more            syslog(LOG_ERR, "%s","Unable to fork() any more.");            #ifdef DGDEBUG                std::cout << "Unable to fork() any more." << std::endl;                std::cout << strerror(errno) << std::endl;                std::cout << "numchildren:" << numchildren << std::endl;            #endif            failurecount++;  // log the error/failure                             // A DoS attack on a server allocated                             // too many children in the conf will                             // kill the server.  But this is user                             // error.            sleep(1);  // need to wait until we have a spare slot            num--;            continue;  // Nothing doing, go back to listening        }        else if(child_pid == 0) {            // I am the child - I am alive!            close(sv[0]);  // we only need our copy of this            tidyUpForChild();            if (!dropPrivCompletely()) {                return -1; //error            }            // no need to deallocate memory etc as already done when fork()ed            int rc = handleConnections(sv[1]);            try {                close(sv[1]);  // connection to parent            } catch (exception& e) {}            try {                serversock.close(); // listening connection

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -