@@ -710,53 +710,116 @@ PHP_FUNCTION(pcntl_signal_dispatch)
710
710
}
711
711
/* }}} */
712
712
713
+ /* Common helper function for these 3 wrapper functions */
714
+ #if defined(HAVE_SIGWAITINFO ) || defined(HAVE_SIGTIMEDWAIT ) || defined(HAVE_SIGPROCMASK )
715
+ static bool php_pcntl_set_user_signal_infos (
716
+ /* const */ HashTable * const user_signals ,
717
+ sigset_t * const set ,
718
+ size_t arg_num
719
+ ) {
720
+ if (zend_hash_num_elements (user_signals ) == 0 ) {
721
+ zend_argument_value_error (arg_num , "cannot be empty" );
722
+ return false;
723
+ }
724
+
725
+ errno = 0 ;
726
+ if (sigemptyset (set ) != 0 ) {
727
+ PCNTL_G (last_error ) = errno ;
728
+ php_error_docref (NULL , E_WARNING , "%s" , strerror (errno ));
729
+ return false;
730
+ }
731
+
732
+ zval * user_signal_no ;
733
+ ZEND_HASH_FOREACH_VAL (user_signals , user_signal_no ) {
734
+ bool failed = true;
735
+ zend_long tmp = zval_try_get_long (user_signal_no , & failed );
736
+
737
+ if (failed ) {
738
+ zend_argument_type_error (arg_num , "signals must be of type int, %s given" , zend_zval_value_name (user_signal_no ));
739
+ return false;
740
+ }
741
+ /* Signals are positive integers */
742
+ if (tmp < 1 || tmp >= PCNTL_G (num_signals )) {
743
+ /* PCNTL_G(num_signals) stores +1 from the last valid signal */
744
+ zend_argument_value_error (arg_num , "signals must be between 1 and %d" , PCNTL_G (num_signals )- 1 );
745
+ return false;
746
+ }
747
+
748
+ int signal_no = (int ) tmp ;
749
+ errno = 0 ;
750
+ if (sigaddset (set , signal_no ) != 0 ) {
751
+ PCNTL_G (last_error ) = errno ;
752
+ php_error_docref (NULL , E_WARNING , "%s" , strerror (errno ));
753
+ return false;
754
+ }
755
+ } ZEND_HASH_FOREACH_END ();
756
+ return true;
757
+ }
758
+ #endif
759
+
713
760
#ifdef HAVE_SIGPROCMASK
714
761
/* {{{ Examine and change blocked signals */
715
762
PHP_FUNCTION (pcntl_sigprocmask )
716
763
{
717
- zend_long how , signo ;
718
- zval * user_set , * user_oldset = NULL , * user_signo ;
719
- sigset_t set , oldset ;
764
+ zend_long how ;
765
+ HashTable * user_set ;
766
+ /* Optional by-ref out-param array of old signals */
767
+ zval * user_old_set = NULL ;
720
768
721
769
ZEND_PARSE_PARAMETERS_START (2 , 3 )
722
770
Z_PARAM_LONG (how )
723
- Z_PARAM_ARRAY (user_set )
771
+ Z_PARAM_ARRAY_HT (user_set )
724
772
Z_PARAM_OPTIONAL
725
- Z_PARAM_ZVAL (user_oldset )
773
+ Z_PARAM_ZVAL (user_old_set )
726
774
ZEND_PARSE_PARAMETERS_END ();
727
775
728
- if (sigemptyset (& set ) != 0 || sigemptyset (& oldset ) != 0 ) {
776
+ if (how != SIG_BLOCK && how != SIG_UNBLOCK && how != SIG_SETMASK ) {
777
+ zend_argument_value_error (1 , "must be one of SIG_BLOCK, SIG_UNBLOCK, or SIG_SETMASK" );
778
+ RETURN_THROWS ();
779
+ }
780
+
781
+ errno = 0 ;
782
+ sigset_t old_set ;
783
+ if (sigemptyset (& old_set ) != 0 ) {
729
784
PCNTL_G (last_error ) = errno ;
730
785
php_error_docref (NULL , E_WARNING , "%s" , strerror (errno ));
731
786
RETURN_FALSE ;
732
787
}
733
788
734
- ZEND_HASH_FOREACH_VAL (Z_ARRVAL_P (user_set ), user_signo ) {
735
- signo = zval_get_long (user_signo );
736
- if (sigaddset (& set , signo ) != 0 ) {
789
+ sigset_t set ;
790
+ /* Can set an empty array of signals for SIG_SETMASK */
791
+ if (how == SIG_SETMASK && zend_hash_num_elements (user_set ) == 0 ) {
792
+ if (sigemptyset (& set ) != 0 ) {
737
793
PCNTL_G (last_error ) = errno ;
738
794
php_error_docref (NULL , E_WARNING , "%s" , strerror (errno ));
739
795
RETURN_FALSE ;
740
796
}
741
- } ZEND_HASH_FOREACH_END ();
797
+ goto skip_setting_user_signals ;
798
+ }
799
+ bool status = php_pcntl_set_user_signal_infos (user_set , & set , 2 );
800
+ /* Some error occurred */
801
+ if (!status ) {
802
+ RETURN_FALSE ;
803
+ }
804
+ skip_setting_user_signals :
742
805
743
- if (sigprocmask (how , & set , & oldset ) != 0 ) {
806
+ if (sigprocmask (how , & set , & old_set ) != 0 ) {
744
807
PCNTL_G (last_error ) = errno ;
745
808
php_error_docref (NULL , E_WARNING , "%s" , strerror (errno ));
746
809
RETURN_FALSE ;
747
810
}
748
811
749
- if (user_oldset != NULL ) {
750
- user_oldset = zend_try_array_init (user_oldset );
751
- if (!user_oldset ) {
812
+ if (user_old_set != NULL ) {
813
+ user_old_set = zend_try_array_init (user_old_set );
814
+ if (!user_old_set ) {
752
815
RETURN_THROWS ();
753
816
}
754
817
755
- for (signo = 1 ; signo < PCNTL_G (num_signals ); ++ signo ) {
756
- if (sigismember (& oldset , signo ) != 1 ) {
818
+ for (int signal_no = 1 ; signal_no < PCNTL_G (num_signals ); ++ signal_no ) {
819
+ if (sigismember (& old_set , signal_no ) != 1 ) {
757
820
continue ;
758
821
}
759
- add_next_index_long (user_oldset , signo );
822
+ add_next_index_long (user_old_set , signal_no );
760
823
}
761
824
}
762
825
@@ -766,50 +829,7 @@ PHP_FUNCTION(pcntl_sigprocmask)
766
829
#endif
767
830
768
831
#ifdef HAVE_STRUCT_SIGINFO_T
769
- # if defined(HAVE_SIGWAITINFO ) && defined(HAVE_SIGTIMEDWAIT )
770
-
771
- static bool php_pcntl_process_user_signal_infos (
772
- /* const */ HashTable * const user_signals ,
773
- sigset_t * const set
774
- ) {
775
- if (zend_hash_num_elements (user_signals ) == 0 ) {
776
- zend_argument_value_error (1 , "cannot be empty" );
777
- return false;
778
- }
779
-
780
- errno = 0 ;
781
- if (sigemptyset (set ) != 0 ) {
782
- PCNTL_G (last_error ) = errno ;
783
- php_error_docref (NULL , E_WARNING , "%s" , strerror (errno ));
784
- return false;
785
- }
786
-
787
- zval * user_signal_no ;
788
- ZEND_HASH_FOREACH_VAL (user_signals , user_signal_no ) {
789
- bool failed = true;
790
- zend_long tmp = zval_try_get_long (user_signal_no , & failed );
791
-
792
- if (failed ) {
793
- zend_argument_type_error (1 , "signals must be of type int, %s given" , zend_zval_value_name (user_signal_no ));
794
- return false;
795
- }
796
- /* Signals are positive integers */
797
- if (tmp < 1 || tmp >= PCNTL_G (num_signals )) {
798
- /* PCNTL_G(num_signals) stores +1 from the last valid signal */
799
- zend_argument_value_error (1 , "signals must be between 1 and %d" , PCNTL_G (num_signals )- 1 );
800
- return false;
801
- }
802
-
803
- int signal_no = (int ) tmp ;
804
- errno = 0 ;
805
- if (sigaddset (set , signal_no ) != 0 ) {
806
- PCNTL_G (last_error ) = errno ;
807
- php_error_docref (NULL , E_WARNING , "%s" , strerror (errno ));
808
- return false;
809
- }
810
- } ZEND_HASH_FOREACH_END ();
811
- return true;
812
- }
832
+ # ifdef HAVE_SIGWAITINFO
813
833
814
834
/* {{{ Synchronously wait for queued signals */
815
835
PHP_FUNCTION (pcntl_sigwaitinfo )
@@ -825,7 +845,7 @@ PHP_FUNCTION(pcntl_sigwaitinfo)
825
845
ZEND_PARSE_PARAMETERS_END ();
826
846
827
847
sigset_t set ;
828
- bool status = php_pcntl_process_user_signal_infos (user_set , & set );
848
+ bool status = php_pcntl_set_user_signal_infos (user_set , & set , 1 );
829
849
/* Some error occurred */
830
850
if (!status ) {
831
851
RETURN_FALSE ;
@@ -851,7 +871,8 @@ PHP_FUNCTION(pcntl_sigwaitinfo)
851
871
RETURN_LONG (signal_no );
852
872
}
853
873
/* }}} */
854
-
874
+ # endif
875
+ # ifdef HAVE_SIGTIMEDWAIT
855
876
/* {{{ Wait for queued signals */
856
877
PHP_FUNCTION (pcntl_sigtimedwait )
857
878
{
@@ -870,7 +891,7 @@ PHP_FUNCTION(pcntl_sigtimedwait)
870
891
ZEND_PARSE_PARAMETERS_END ();
871
892
872
893
sigset_t set ;
873
- bool status = php_pcntl_process_user_signal_infos (user_set , & set );
894
+ bool status = php_pcntl_set_user_signal_infos (user_set , & set , 1 );
874
895
/* Some error occurred */
875
896
if (!status ) {
876
897
RETURN_FALSE ;
0 commit comments