diff --git a/src/main.c b/src/main.c
index a9d3a644..f98c8c0b 100644
--- a/src/main.c
+++ b/src/main.c
@@ -227,7 +227,7 @@ static const int default_job_slots = INVALID_JOB_SLOTS;
 
 /* Value of job_slots that means no limit.  */
 
-static const int inf_jobs = 0;
+static const int inf_jobs = 10000;
 
 /* Authorization for the jobserver.  */
 
@@ -788,6 +788,36 @@ debug_signal_handler (int sig UNUSED)
 {
   db_level = db_level ? DB_NONE : DB_BASIC;
 }
+
+static void
+decrease_job_signal_handler (int sig UNUSED)
+{
+  if (master_job_slots > 1)
+  {
+    master_job_slots--;
+    jobserver_signal_safe_string_to_stderr("** Decreasing jobs to ");
+    jobserver_signal_safe_number_to_stderr(master_job_slots);
+    jobserver_signal_safe_string_to_stderr(" **\n");
+    jobserver_signal_safe_decrease_jobs();
+  }
+  else
+  {
+    jobserver_signal_safe_string_to_stderr("** Unable to decrease jobs from ");
+    jobserver_signal_safe_number_to_stderr(master_job_slots);
+    jobserver_signal_safe_string_to_stderr(" **\n");
+  }
+}
+
+static void
+increase_job_signal_handler (int sig UNUSED)
+{
+  bsd_signal (SIGUSR1, decrease_job_signal_handler);
+  jobserver_signal_safe_increase_jobs();
+  master_job_slots++;
+  jobserver_signal_safe_string_to_stderr("** Increased jobs to ");
+  jobserver_signal_safe_number_to_stderr(master_job_slots);
+  jobserver_signal_safe_string_to_stderr(" **\n");
+}
 #endif
 
 static void
@@ -2024,6 +2054,9 @@ main (int argc, char **argv, char **envp)
 #ifdef SIGUSR1
   bsd_signal (SIGUSR1, debug_signal_handler);
 #endif
+#ifdef SIGUSR2
+  bsd_signal (SIGUSR2, increase_job_signal_handler);
+#endif
 
   /* Define the initial list of suffixes for old-style rules.  */
   set_default_suffixes ();
@@ -2214,7 +2247,7 @@ main (int argc, char **argv, char **envp)
      submakes it's the token they were given by their parent.  For the top
      make, we just subtract one from the number the user wants.  */
 
-  if (job_slots > 1 && jobserver_setup (job_slots - 1, jobserver_style))
+  if (!jobserver_auth && jobserver_setup (job_slots - 1, jobserver_style))
     {
       /* Fill in the jobserver_auth for our children.  */
       jobserver_auth = jobserver_get_auth ();
diff --git a/src/os.h b/src/os.h
old mode 100644
new mode 100755
index 05777a60..59bb613b
--- a/src/os.h
+++ b/src/os.h
@@ -93,6 +93,13 @@ void jobserver_pre_acquire (void);
    exiting or a timeout.    */
 unsigned int jobserver_acquire (int timeout);
 
+#ifdef SIGUSR1
+void jobserver_signal_safe_increase_jobs(void);
+void jobserver_signal_safe_decrease_jobs(void);
+void jobserver_signal_safe_string_to_stderr(const char *string);
+void jobserver_signal_safe_number_to_stderr(long nr);
+#endif
+
 #else
 
 #define jobserver_enabled()             (0)
diff --git a/src/posixos.c b/src/posixos.c
old mode 100644
new mode 100755
index 0cc0a585..68e067b8
--- a/src/posixos.c
+++ b/src/posixos.c
@@ -207,7 +207,11 @@ jobserver_setup (int slots, const char *style)
   if (make_job_rfd () < 0)
     pfatal_with_name (_("duping jobs pipe"));
 
-  while (slots--)
+  if(slots<0) /* this should not happen */
+  {
+    slots=2; /* some reasonable value */
+  }
+  while (slots-- > 0)
     {
       EINTRLOOP (r, write (job_fds[1], &token, 1));
       if (r != 1)
@@ -894,3 +898,92 @@ os_anontmp ()
 
   return fd;
 }
+
+#ifdef SIGUSR1
+#include <sys/wait.h>
+
+void jobserver_signal_safe_increase_jobs(void)
+{
+  int r;
+  EINTRLOOP (r, write (job_fds[1], &token, 1));
+}
+
+void jobserver_signal_safe_decrease_jobs(void)
+{
+  pid_t pid = fork();
+  if(pid>0)
+  {
+    waitpid(pid, NULL, 0);
+    return;
+  }
+  else
+  {
+    pid = fork(); /* avoid zombies */
+    if(!pid)
+    {
+      char intake;
+      int r;
+      struct timespec spec = {0, 1000000}; /* 1 ms */
+      fd_set readfds;
+      sigset_t empty;
+
+      sigemptyset (&empty);
+
+      /* set_blocking (job_fds[0], 1); */
+      do
+      {
+        FD_ZERO (&readfds);
+        FD_SET (job_fds[0], &readfds);
+
+        r = pselect (job_fds[0]+1, &readfds, NULL, NULL, &spec, &empty);
+        if(r==1) /* not timeout */
+        {
+          EINTRLOOP (r, read (job_fds[0], &intake, 1));
+          if(r==1)
+          {
+            jobserver_signal_safe_string_to_stderr("** Revoked 1 job **\n");
+          }
+          else
+          {
+            jobserver_signal_safe_string_to_stderr(
+              "** Failed attempt revoking job **\n");
+          }
+        }
+        if(r==-1 && errno==EBADF)
+        {
+          exit(0);
+        }
+      } while(r<1); /* half busy waiting in attempt to get
+                       the token before others */
+    }
+    exit(0);
+  }
+}
+
+void jobserver_signal_safe_string_to_stderr(const char *string)
+{
+  /* trying to translate with gettext would not be signal safe */
+  write(2, string, strlen(string));
+}
+
+void jobserver_signal_safe_number_to_stderr(long nr)
+{
+  char buf[50];
+  char *p=&buf[50]; /* yes, this is outside, will be corrected before use */
+  int numbers=0;
+  if(nr<0)
+  {
+    nr*=-1;
+    write(2, "-", 1);
+  }
+  do
+  {
+    p--;
+    numbers++;
+    *p='0'+nr%10;
+    nr/=10;
+  }while(nr && numbers<50);
+  write(2, p, numbers);
+}
+
+#endif
