Skip to content

Instantly share code, notes, and snippets.

@Roguelazer
Created December 4, 2014 04:49
Show Gist options
  • Save Roguelazer/59d253a19f0e335a76dc to your computer and use it in GitHub Desktop.
Save Roguelazer/59d253a19f0e335a76dc to your computer and use it in GitHub Desktop.
limit_nsca_child_processes.diff
--- nsca~/src/nsca.c 2014-12-03 20:44:00.000000000 -0800
+++ nsca/src/nsca.c 2014-12-03 20:46:29.098392130 -0800
@@ -21,6 +21,9 @@
#include "../include/utils.h"
#include "../include/nsca.h"
+#include <stdio.h>
+#include <errno.h>
+
static int server_port=DEFAULT_SERVER_PORT;
static char server_address[16]="0.0.0.0";
@@ -66,6 +69,9 @@
int nrhand=0;
int nwhand=0;
int npfds=0;
+
+int live_children=0;
+int max_children=100;
#ifdef HAVE_LIBWRAP
int allow_severity=LOG_INFO;
@@ -457,6 +463,9 @@
else if(!strcmp(varname,"pid_file"))
pid_file=strdup(varvalue);
+ else if(!strcmp(varname,"max_children"))
+ max_children = strtoul(varvalue, NULL, 10);
+
else{
syslog(LOG_ERR,"Unknown option specified in config file '%s' - Line %d\n",filename,line);
@@ -475,7 +484,9 @@
/* get rid of all the children we can... */
static void reap_children(int sig){
- while(waitpid(-1,NULL,WNOHANG)>0);
+ while(waitpid(-1,NULL,WNOHANG)>0) {
+ live_children--;
+ }
return;
}
@@ -770,6 +781,11 @@
/* wait for a connection request */
while(1){
+ if(mode==MULTI_PROCESS_DAEMON) {
+ /* Check for children every loop interation */
+ reap_children(0);
+ }
+
/* we got a live one... */
if((new_sd=accept(sock,0,0))>=0)
break;
@@ -820,22 +836,6 @@
}
#endif
-
- /* fork() if we have to... */
- if(mode==MULTI_PROCESS_DAEMON){
-
- pid=fork();
- if(pid){
- /* parent doesn't need the new connection */
- close(new_sd);
- return;
- }
- else{
- /* child does not need to listen for connections */
- close(sock);
- }
- }
-
/* find out who just connected... */
addrlen=sizeof(addr);
rc=getpeername(new_sd,&addr,&addrlen);
@@ -853,17 +853,44 @@
nptr=(struct sockaddr_in *)&addr;
+
+ /* fork() if we have to... */
+ if(mode==MULTI_PROCESS_DAEMON){
+ if (live_children >= max_children) {
+ syslog(LOG_ERR, "already have %d children, refusing connect from %s", live_children, inet_ntoa(nptr->sin_addr));
+ close(new_sd);
+ return;
+ }
+
+ pid=fork();
+ if(pid > 0){
+ live_children++;
+ /* parent doesn't need the new connection */
+ close(new_sd);
+ return;
+ }
+ else if (pid == 0){
+ /* child does not need to listen for connections */
+ close(sock);
+ }
+ } else {
+ syslog(LOG_ERR, "fork failed! errno %d, %s", errno, strerror(errno));
+ close(new_sd);
+ return;
+ }
+
/* log info to syslog facility */
if(debug==TRUE)
syslog(LOG_DEBUG,"Connection from %s port %d",inet_ntoa(nptr->sin_addr),nptr->sin_port);
/* handle the connection */
- if(mode==SINGLE_PROCESS_DAEMON)
+ if(mode==SINGLE_PROCESS_DAEMON) {
/* mark the connection as ready to be handled */
register_write_handler(new_sd, handle_connection, NULL);
- else
+ } else {
/* handle the client connection */
handle_connection(new_sd, NULL);
+ }
return;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment