@@ -705,53 +705,107 @@ PHP_FUNCTION(pcntl_signal_dispatch)
705
705
}
706
706
/* }}} */
707
707
708
+ /* Common helper function for these 3 wrapper functions */
709
+ #if defined(HAVE_SIGWAITINFO ) || defined(HAVE_SIGTIMEDWAIT ) || defined(HAVE_SIGPROCMASK )
710
+ static bool php_pcntl_set_user_signal_infos (
711
+ /* const */ HashTable * const user_signals ,
712
+ sigset_t * const set ,
713
+ size_t arg_num ,
714
+ bool allow_empty_signal_array
715
+ ) {
716
+ if (!allow_empty_signal_array && zend_hash_num_elements (user_signals ) == 0 ) {
717
+ zend_argument_value_error (arg_num , "cannot be empty" );
718
+ return false;
719
+ }
720
+
721
+ errno = 0 ;
722
+ if (sigemptyset (set ) != 0 ) {
723
+ PCNTL_G (last_error ) = errno ;
724
+ php_error_docref (NULL , E_WARNING , "%s" , strerror (errno ));
725
+ return false;
726
+ }
727
+
728
+ zval * user_signal_no ;
729
+ ZEND_HASH_FOREACH_VAL (user_signals , user_signal_no ) {
730
+ bool failed = true;
731
+ zend_long tmp = zval_try_get_long (user_signal_no , & failed );
732
+
733
+ if (failed ) {
734
+ zend_argument_type_error (arg_num , "signals must be of type int, %s given" , zend_zval_value_name (user_signal_no ));
735
+ return false;
736
+ }
737
+ /* Signals are positive integers */
738
+ if (tmp < 1 || tmp >= PCNTL_G (num_signals )) {
739
+ /* PCNTL_G(num_signals) stores +1 from the last valid signal */
740
+ zend_argument_value_error (arg_num , "signals must be between 1 and %d" , PCNTL_G (num_signals )- 1 );
741
+ return false;
742
+ }
743
+
744
+ int signal_no = (int ) tmp ;
745
+ errno = 0 ;
746
+ if (sigaddset (set , signal_no ) != 0 ) {
747
+ PCNTL_G (last_error ) = errno ;
748
+ php_error_docref (NULL , E_WARNING , "%s" , strerror (errno ));
749
+ return false;
750
+ }
751
+ } ZEND_HASH_FOREACH_END ();
752
+ return true;
753
+ }
754
+ #endif
755
+
708
756
#ifdef HAVE_SIGPROCMASK
709
757
/* {{{ Examine and change blocked signals */
710
758
PHP_FUNCTION (pcntl_sigprocmask )
711
759
{
712
- zend_long how , signo ;
713
- zval * user_set , * user_oldset = NULL , * user_signo ;
714
- sigset_t set , oldset ;
760
+ zend_long how ;
761
+ HashTable * user_set ;
762
+ /* Optional by-ref out-param array of old signals */
763
+ zval * user_old_set = NULL ;
715
764
716
765
ZEND_PARSE_PARAMETERS_START (2 , 3 )
717
766
Z_PARAM_LONG (how )
718
- Z_PARAM_ARRAY (user_set )
767
+ Z_PARAM_ARRAY_HT (user_set )
719
768
Z_PARAM_OPTIONAL
720
- Z_PARAM_ZVAL (user_oldset )
769
+ Z_PARAM_ZVAL (user_old_set )
721
770
ZEND_PARSE_PARAMETERS_END ();
722
771
723
- if (sigemptyset (& set ) != 0 || sigemptyset (& oldset ) != 0 ) {
772
+ if (how != SIG_BLOCK && how != SIG_UNBLOCK && how != SIG_SETMASK ) {
773
+ zend_argument_value_error (1 , "must be one of SIG_BLOCK, SIG_UNBLOCK, or SIG_SETMASK" );
774
+ RETURN_THROWS ();
775
+ }
776
+
777
+ errno = 0 ;
778
+ sigset_t old_set ;
779
+ if (sigemptyset (& old_set ) != 0 ) {
724
780
PCNTL_G (last_error ) = errno ;
725
781
php_error_docref (NULL , E_WARNING , "%s" , strerror (errno ));
726
782
RETURN_FALSE ;
727
783
}
728
784
729
- ZEND_HASH_FOREACH_VAL (Z_ARRVAL_P (user_set ), user_signo ) {
730
- signo = zval_get_long (user_signo );
731
- if (sigaddset (& set , signo ) != 0 ) {
732
- PCNTL_G (last_error ) = errno ;
733
- php_error_docref (NULL , E_WARNING , "%s" , strerror (errno ));
734
- RETURN_FALSE ;
735
- }
736
- } ZEND_HASH_FOREACH_END ();
785
+ sigset_t set ;
786
+ bool status = php_pcntl_set_user_signal_infos (user_set , & set , 2 , /* allow_empty_signal_array */ how == SIG_SETMASK );
787
+ /* Some error occurred */
788
+ if (!status ) {
789
+ RETURN_FALSE ;
790
+ }
737
791
738
- if (sigprocmask (how , & set , & oldset ) != 0 ) {
792
+ if (sigprocmask (how , & set , & old_set ) != 0 ) {
739
793
PCNTL_G (last_error ) = errno ;
740
794
php_error_docref (NULL , E_WARNING , "%s" , strerror (errno ));
741
795
RETURN_FALSE ;
742
796
}
743
797
744
- if (user_oldset != NULL ) {
745
- user_oldset = zend_try_array_init (user_oldset );
746
- if (!user_oldset ) {
798
+ if (user_old_set != NULL ) {
799
+ user_old_set = zend_try_array_init (user_old_set );
800
+ if (!user_old_set ) {
747
801
RETURN_THROWS ();
748
802
}
749
803
750
- for (signo = 1 ; signo < PCNTL_G (num_signals ); ++ signo ) {
751
- if (sigismember (& oldset , signo ) != 1 ) {
804
+ for (int signal_no = 1 ; signal_no < PCNTL_G (num_signals ); ++ signal_no ) {
805
+ if (sigismember (& old_set , signal_no ) != 1 ) {
752
806
continue ;
753
807
}
754
- add_next_index_long (user_oldset , signo );
808
+ add_next_index_long (user_old_set , signal_no );
755
809
}
756
810
}
757
811
@@ -761,82 +815,109 @@ PHP_FUNCTION(pcntl_sigprocmask)
761
815
#endif
762
816
763
817
#ifdef HAVE_STRUCT_SIGINFO_T
764
- # if defined(HAVE_SIGWAITINFO ) && defined(HAVE_SIGTIMEDWAIT )
765
- static void pcntl_sigwaitinfo (INTERNAL_FUNCTION_PARAMETERS , int timedwait ) /* {{{ */
818
+ # ifdef HAVE_SIGWAITINFO
819
+
820
+ /* {{{ Synchronously wait for queued signals */
821
+ PHP_FUNCTION (pcntl_sigwaitinfo )
766
822
{
767
- zval * user_set , * user_signo , * user_siginfo = NULL ;
768
- zend_long tv_sec = 0 , tv_nsec = 0 ;
769
- sigset_t set ;
770
- int signo ;
771
- siginfo_t siginfo ;
772
- struct timespec timeout ;
773
-
774
- if (timedwait ) {
775
- ZEND_PARSE_PARAMETERS_START (1 , 4 )
776
- Z_PARAM_ARRAY (user_set )
777
- Z_PARAM_OPTIONAL
778
- Z_PARAM_ZVAL (user_siginfo )
779
- Z_PARAM_LONG (tv_sec )
780
- Z_PARAM_LONG (tv_nsec )
781
- ZEND_PARSE_PARAMETERS_END ();
782
- } else {
783
- ZEND_PARSE_PARAMETERS_START (1 , 2 )
784
- Z_PARAM_ARRAY (user_set )
785
- Z_PARAM_OPTIONAL
786
- Z_PARAM_ZVAL (user_siginfo )
787
- ZEND_PARSE_PARAMETERS_END ();
788
- }
823
+ HashTable * user_set ;
824
+ /* Optional by-ref array of ints */
825
+ zval * user_siginfo = NULL ;
789
826
790
- if (sigemptyset (& set ) != 0 ) {
791
- PCNTL_G (last_error ) = errno ;
792
- php_error_docref (NULL , E_WARNING , "%s" , strerror (errno ));
827
+ ZEND_PARSE_PARAMETERS_START (1 , 2 )
828
+ Z_PARAM_ARRAY_HT (user_set )
829
+ Z_PARAM_OPTIONAL
830
+ Z_PARAM_ZVAL (user_siginfo )
831
+ ZEND_PARSE_PARAMETERS_END ();
832
+
833
+ sigset_t set ;
834
+ bool status = php_pcntl_set_user_signal_infos (user_set , & set , 1 , /* allow_empty_signal_array */ false);
835
+ /* Some error occurred */
836
+ if (!status ) {
793
837
RETURN_FALSE ;
794
838
}
795
839
796
- ZEND_HASH_FOREACH_VAL (Z_ARRVAL_P (user_set ), user_signo ) {
797
- signo = zval_get_long (user_signo );
798
- if (sigaddset (& set , signo ) != 0 ) {
799
- PCNTL_G (last_error ) = errno ;
800
- php_error_docref (NULL , E_WARNING , "%s" , strerror (errno ));
801
- RETURN_FALSE ;
802
- }
803
- } ZEND_HASH_FOREACH_END ();
804
-
805
- if (timedwait ) {
806
- timeout .tv_sec = (time_t ) tv_sec ;
807
- timeout .tv_nsec = tv_nsec ;
808
- signo = sigtimedwait (& set , & siginfo , & timeout );
809
- } else {
810
- signo = sigwaitinfo (& set , & siginfo );
811
- }
812
- if (signo == -1 && errno != EAGAIN ) {
840
+ errno = 0 ;
841
+ siginfo_t siginfo ;
842
+ int signal_no = sigwaitinfo (& set , & siginfo );
843
+ /* sigwaitinfo() never sets errno to EAGAIN according to POSIX */
844
+ if (signal_no == -1 ) {
813
845
PCNTL_G (last_error ) = errno ;
814
846
php_error_docref (NULL , E_WARNING , "%s" , strerror (errno ));
847
+ RETURN_FALSE ;
815
848
}
816
849
817
- /*
818
- * sigtimedwait and sigwaitinfo can return 0 on success on some
819
- * platforms, e.g. NetBSD
820
- */
821
- if (!signo && siginfo .si_signo ) {
822
- signo = siginfo .si_signo ;
850
+ /* sigwaitinfo can return 0 on success on some platforms, e.g. NetBSD */
851
+ if (!signal_no && siginfo .si_signo ) {
852
+ signal_no = siginfo .si_signo ;
823
853
}
824
- pcntl_siginfo_to_zval (signo , & siginfo , user_siginfo );
825
- RETURN_LONG (signo );
826
- }
827
- /* }}} */
828
854
829
- /* {{{ Synchronously wait for queued signals */
830
- PHP_FUNCTION (pcntl_sigwaitinfo )
831
- {
832
- pcntl_sigwaitinfo (INTERNAL_FUNCTION_PARAM_PASSTHRU , 0 );
855
+ pcntl_siginfo_to_zval (signal_no , & siginfo , user_siginfo );
856
+
857
+ RETURN_LONG (signal_no );
833
858
}
834
859
/* }}} */
835
-
860
+ # endif
861
+ # ifdef HAVE_SIGTIMEDWAIT
836
862
/* {{{ Wait for queued signals */
837
863
PHP_FUNCTION (pcntl_sigtimedwait )
838
864
{
839
- pcntl_sigwaitinfo (INTERNAL_FUNCTION_PARAM_PASSTHRU , 1 );
865
+ HashTable * user_set ;
866
+ /* Optional by-ref array of ints */
867
+ zval * user_siginfo = NULL ;
868
+ zend_long tv_sec = 0 ;
869
+ zend_long tv_nsec = 0 ;
870
+
871
+ ZEND_PARSE_PARAMETERS_START (1 , 4 )
872
+ Z_PARAM_ARRAY_HT (user_set )
873
+ Z_PARAM_OPTIONAL
874
+ Z_PARAM_ZVAL (user_siginfo )
875
+ Z_PARAM_LONG (tv_sec )
876
+ Z_PARAM_LONG (tv_nsec )
877
+ ZEND_PARSE_PARAMETERS_END ();
878
+
879
+ sigset_t set ;
880
+ bool status = php_pcntl_set_user_signal_infos (user_set , & set , 1 , /* allow_empty_signal_array */ false);
881
+ /* Some error occurred */
882
+ if (!status ) {
883
+ RETURN_FALSE ;
884
+ }
885
+ if (tv_sec < 0 ) {
886
+ zend_argument_value_error (3 , "must be greater than or equal to 0" );
887
+ RETURN_THROWS ();
888
+ }
889
+ /* Nanosecond between 0 and 1e9 */
890
+ if (tv_nsec < 0 || tv_nsec >= 1000000000 ) {
891
+ zend_argument_value_error (4 , "must be between 0 and 1e9" );
892
+ RETURN_THROWS ();
893
+ }
894
+ if (UNEXPECTED (tv_sec == 0 && tv_nsec == 0 )) {
895
+ zend_value_error ("pcntl_sigtimedwait(): At least one of argument #3 ($seconds) or argument #4 ($nanoseconds) must be greater than 0" );
896
+ RETURN_THROWS ();
897
+ }
898
+
899
+ errno = 0 ;
900
+ siginfo_t siginfo ;
901
+ struct timespec timeout ;
902
+ timeout .tv_sec = (time_t ) tv_sec ;
903
+ timeout .tv_nsec = tv_nsec ;
904
+ int signal_no = sigtimedwait (& set , & siginfo , & timeout );
905
+ if (signal_no == -1 ) {
906
+ if (errno != EAGAIN ) {
907
+ PCNTL_G (last_error ) = errno ;
908
+ php_error_docref (NULL , E_WARNING , "%s" , strerror (errno ));
909
+ }
910
+ RETURN_FALSE ;
911
+ }
912
+
913
+ /* sigtimedwait can return 0 on success on some platforms, e.g. NetBSD */
914
+ if (!signal_no && siginfo .si_signo ) {
915
+ signal_no = siginfo .si_signo ;
916
+ }
917
+
918
+ pcntl_siginfo_to_zval (signal_no , & siginfo , user_siginfo );
919
+
920
+ RETURN_LONG (signal_no );
840
921
}
841
922
/* }}} */
842
923
# endif
0 commit comments