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>


2354 
2355 /*
2356  * Return true if the signal number is in range
2357  * and the signal code specifies signal queueing.
2358  */
2359 int
2360 sigwillqueue(int sig, int code)
2361 {
2362         if (sig >= 0 && sig < NSIG) {
2363                 switch (code) {
2364                 case SI_QUEUE:
2365                 case SI_TIMER:
2366                 case SI_ASYNCIO:
2367                 case SI_MESGQ:
2368                         return (1);
2369                 }
2370         }
2371         return (0);
2372 }
2373 
2374 #ifndef UCHAR_MAX
2375 #define UCHAR_MAX       255
2376 #endif
2377 
2378 /*
2379  * The entire pool (with maxcount entries) is pre-allocated at
2380  * the first sigqueue/signotify call.
2381  */
2382 sigqhdr_t *
2383 sigqhdralloc(size_t size, uint_t maxcount)
2384 {
2385         size_t i;
2386         sigqueue_t *sq, *next;
2387         sigqhdr_t *sqh;
2388 
2389         i = (maxcount * size) + sizeof (sigqhdr_t);
2390         ASSERT(maxcount <= UCHAR_MAX && i <= USHRT_MAX);






2391         sqh = kmem_alloc(i, KM_SLEEP);
2392         sqh->sqb_count = (uchar_t)maxcount;
2393         sqh->sqb_maxcount = (uchar_t)maxcount;
2394         sqh->sqb_size = (ushort_t)i;
2395         sqh->sqb_pexited = 0;
2396         sqh->sqb_sent = 0;
2397         sqh->sqb_free = sq = (sigqueue_t *)(sqh + 1);
2398         for (i = maxcount - 1; i != 0; i--) {
2399                 next = (sigqueue_t *)((uintptr_t)sq + size);
2400                 sq->sq_next = next;
2401                 sq = next;
2402         }
2403         sq->sq_next = NULL;
2404         cv_init(&sqh->sqb_cv, NULL, CV_DEFAULT, NULL);
2405         mutex_init(&sqh->sqb_lock, NULL, MUTEX_DEFAULT, NULL);
2406         return (sqh);
2407 }
2408 
2409 static void sigqrel(sigqueue_t *);
2410 
2411 /*
2412  * allocate a sigqueue/signotify structure from the per process
2413  * pre-allocated pool.

2414  */
2415 sigqueue_t *
2416 sigqalloc(sigqhdr_t *sqh)
2417 {
2418         sigqueue_t *sq = NULL;
2419 
2420         ASSERT(MUTEX_HELD(&curproc->p_lock));
2421 
2422         if (sqh != NULL) {
2423                 mutex_enter(&sqh->sqb_lock);
2424                 if (sqh->sqb_count > 0) {
2425                         sqh->sqb_count--;







2426                         sq = sqh->sqb_free;

2427                         sqh->sqb_free = sq->sq_next;

2428                         mutex_exit(&sqh->sqb_lock);
2429                         bzero(&sq->sq_info, sizeof (k_siginfo_t));
2430                         sq->sq_backptr = sqh;
2431                         sq->sq_func = sigqrel;
2432                         sq->sq_next = NULL;
2433                         sq->sq_external = 0;
2434                 } else {
2435                         mutex_exit(&sqh->sqb_lock);
2436                 }
2437         }
2438         return (sq);
2439 }
2440 
2441 /*
2442  * Return a sigqueue structure back to the pre-allocated pool.
2443  */
2444 static void
2445 sigqrel(sigqueue_t *sq)
2446 {
2447         sigqhdr_t *sqh;
2448 
2449         /* make sure that p_lock of the affected process is held */
2450 
2451         sqh = (sigqhdr_t *)sq->sq_backptr;




2354 
2355 /*
2356  * Return true if the signal number is in range
2357  * and the signal code specifies signal queueing.
2358  */
2359 int
2360 sigwillqueue(int sig, int code)
2361 {
2362         if (sig >= 0 && sig < NSIG) {
2363                 switch (code) {
2364                 case SI_QUEUE:
2365                 case SI_TIMER:
2366                 case SI_ASYNCIO:
2367                 case SI_MESGQ:
2368                         return (1);
2369                 }
2370         }
2371         return (0);
2372 }
2373 




2374 /*
2375  * The pre-allocated pool (with _SIGQUEUE_PREALLOC entries) is
2376  * allocated at the first sigqueue/signotify call.
2377  */
2378 sigqhdr_t *
2379 sigqhdralloc(size_t size, uint_t maxcount)
2380 {
2381         size_t i;
2382         sigqueue_t *sq, *next;
2383         sigqhdr_t *sqh;
2384 
2385         /*
2386          * Before the introduction of process.max-sigqueue-size
2387          * _SC_SIGQUEUE_MAX had this static value.
2388          */
2389 #define _SIGQUEUE_PREALLOC      32
2390 
2391         i = (_SIGQUEUE_PREALLOC * size) + sizeof (sigqhdr_t);
2392         ASSERT(maxcount <= INT_MAX);
2393         sqh = kmem_alloc(i, KM_SLEEP);
2394         sqh->sqb_count = maxcount;
2395         sqh->sqb_maxcount = maxcount;
2396         sqh->sqb_size = i;
2397         sqh->sqb_pexited = 0;
2398         sqh->sqb_sent = 0;
2399         sqh->sqb_free = sq = (sigqueue_t *)(sqh + 1);
2400         for (i = _SIGQUEUE_PREALLOC - 1; i != 0; i--) {
2401                 next = (sigqueue_t *)((uintptr_t)sq + size);
2402                 sq->sq_next = next;
2403                 sq = next;
2404         }
2405         sq->sq_next = NULL;
2406         cv_init(&sqh->sqb_cv, NULL, CV_DEFAULT, NULL);
2407         mutex_init(&sqh->sqb_lock, NULL, MUTEX_DEFAULT, NULL);
2408         return (sqh);
2409 }
2410 
2411 static void sigqrel(sigqueue_t *);
2412 
2413 /*
2414  * Allocate a sigqueue/signotify structure from the per process
2415  * pre-allocated pool or allocate a new sigqueue/signotify structure
2416  * if the pre-allocated pool is exhausted.
2417  */
2418 sigqueue_t *
2419 sigqalloc(sigqhdr_t *sqh)
2420 {
2421         sigqueue_t *sq = NULL;
2422 
2423         ASSERT(MUTEX_HELD(&curproc->p_lock));
2424 
2425         if (sqh != NULL) {
2426                 mutex_enter(&sqh->sqb_lock);
2427                 if (sqh->sqb_count > 0) {
2428                         sqh->sqb_count--;
2429                         if (sqh->sqb_free == NULL) {
2430                                 /*
2431                                  * The pre-allocated pool is exhausted.
2432                                  */
2433                                 sq = kmem_alloc(sizeof (sigqueue_t), KM_SLEEP);
2434                                 sq->sq_func = NULL;
2435                         } else {
2436                                 sq = sqh->sqb_free;
2437                                 sq->sq_func = sigqrel;
2438                                 sqh->sqb_free = sq->sq_next;
2439                         }
2440                         mutex_exit(&sqh->sqb_lock);
2441                         bzero(&sq->sq_info, sizeof (k_siginfo_t));
2442                         sq->sq_backptr = sqh;

2443                         sq->sq_next = NULL;
2444                         sq->sq_external = 0;
2445                 } else {
2446                         mutex_exit(&sqh->sqb_lock);
2447                 }
2448         }
2449         return (sq);
2450 }
2451 
2452 /*
2453  * Return a sigqueue structure back to the pre-allocated pool.
2454  */
2455 static void
2456 sigqrel(sigqueue_t *sq)
2457 {
2458         sigqhdr_t *sqh;
2459 
2460         /* make sure that p_lock of the affected process is held */
2461 
2462         sqh = (sigqhdr_t *)sq->sq_backptr;