Print this page
3830 SIGQUEUE_MAX's limit of 32 is too low
Reviewed by: Cedric Blancher <cedric.blancher@gmail.com>
Reviewed by: John Kennedy <john.kennedy@delphix.com>
Reviewed by: Irek Szczesniak <iszczesniak@gmail.com>

@@ -2369,35 +2369,37 @@
                 }
         }
         return (0);
 }
 
-#ifndef UCHAR_MAX
-#define UCHAR_MAX       255
-#endif
-
 /*
- * The entire pool (with maxcount entries) is pre-allocated at
- * the first sigqueue/signotify call.
+ * The pre-allocated pool (with _SIGQUEUE_PREALLOC entries) is
+ * allocated at the first sigqueue/signotify call.
  */
 sigqhdr_t *
 sigqhdralloc(size_t size, uint_t maxcount)
 {
         size_t i;
         sigqueue_t *sq, *next;
         sigqhdr_t *sqh;
 
-        i = (maxcount * size) + sizeof (sigqhdr_t);
-        ASSERT(maxcount <= UCHAR_MAX && i <= USHRT_MAX);
+        /*
+         * Before the introduction of process.max-sigqueue-size
+         * _SC_SIGQUEUE_MAX had this static value.
+         */
+#define _SIGQUEUE_PREALLOC      32
+
+        i = (_SIGQUEUE_PREALLOC * size) + sizeof (sigqhdr_t);
+        ASSERT(maxcount <= INT_MAX);
         sqh = kmem_alloc(i, KM_SLEEP);
-        sqh->sqb_count = (uchar_t)maxcount;
-        sqh->sqb_maxcount = (uchar_t)maxcount;
-        sqh->sqb_size = (ushort_t)i;
+        sqh->sqb_count = maxcount;
+        sqh->sqb_maxcount = maxcount;
+        sqh->sqb_size = i;
         sqh->sqb_pexited = 0;
         sqh->sqb_sent = 0;
         sqh->sqb_free = sq = (sigqueue_t *)(sqh + 1);
-        for (i = maxcount - 1; i != 0; i--) {
+        for (i = _SIGQUEUE_PREALLOC - 1; i != 0; i--) {
                 next = (sigqueue_t *)((uintptr_t)sq + size);
                 sq->sq_next = next;
                 sq = next;
         }
         sq->sq_next = NULL;

@@ -2407,12 +2409,13 @@
 }
 
 static void sigqrel(sigqueue_t *);
 
 /*
- * allocate a sigqueue/signotify structure from the per process
- * pre-allocated pool.
+ * Allocate a sigqueue/signotify structure from the per process
+ * pre-allocated pool or allocate a new sigqueue/signotify structure
+ * if the pre-allocated pool is exhausted.
  */
 sigqueue_t *
 sigqalloc(sigqhdr_t *sqh)
 {
         sigqueue_t *sq = NULL;

@@ -2421,16 +2424,24 @@
 
         if (sqh != NULL) {
                 mutex_enter(&sqh->sqb_lock);
                 if (sqh->sqb_count > 0) {
                         sqh->sqb_count--;
+                        if (sqh->sqb_free == NULL) {
+                                /*
+                                 * The pre-allocated pool is exhausted.
+                                 */
+                                sq = kmem_alloc(sizeof (sigqueue_t), KM_SLEEP);
+                                sq->sq_func = NULL;
+                        } else {
                         sq = sqh->sqb_free;
+                                sq->sq_func = sigqrel;
                         sqh->sqb_free = sq->sq_next;
+                        }
                         mutex_exit(&sqh->sqb_lock);
                         bzero(&sq->sq_info, sizeof (k_siginfo_t));
                         sq->sq_backptr = sqh;
-                        sq->sq_func = sigqrel;
                         sq->sq_next = NULL;
                         sq->sq_external = 0;
                 } else {
                         mutex_exit(&sqh->sqb_lock);
                 }