@@ -767,81 +767,135 @@ PHP_FUNCTION(pcntl_sigprocmask)
767
767
768
768
#ifdef HAVE_STRUCT_SIGINFO_T
769
769
# if defined(HAVE_SIGWAITINFO ) && defined(HAVE_SIGTIMEDWAIT )
770
- static void pcntl_sigwaitinfo (INTERNAL_FUNCTION_PARAMETERS , int timedwait ) /* {{{ */
771
- {
772
- zval * user_set , * user_signo , * user_siginfo = NULL ;
773
- zend_long tv_sec = 0 , tv_nsec = 0 ;
774
- sigset_t set ;
775
- int signo ;
776
- siginfo_t siginfo ;
777
- struct timespec timeout ;
778
-
779
- if (timedwait ) {
780
- ZEND_PARSE_PARAMETERS_START (1 , 4 )
781
- Z_PARAM_ARRAY (user_set )
782
- Z_PARAM_OPTIONAL
783
- Z_PARAM_ZVAL (user_siginfo )
784
- Z_PARAM_LONG (tv_sec )
785
- Z_PARAM_LONG (tv_nsec )
786
- ZEND_PARSE_PARAMETERS_END ();
787
- } else {
788
- ZEND_PARSE_PARAMETERS_START (1 , 2 )
789
- Z_PARAM_ARRAY (user_set )
790
- Z_PARAM_OPTIONAL
791
- Z_PARAM_ZVAL (user_siginfo )
792
- ZEND_PARSE_PARAMETERS_END ();
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;
793
778
}
794
779
795
- if (sigemptyset (& set ) != 0 ) {
780
+ errno = 0 ;
781
+ if (sigemptyset (set ) != 0 ) {
796
782
PCNTL_G (last_error ) = errno ;
797
783
php_error_docref (NULL , E_WARNING , "%s" , strerror (errno ));
798
- RETURN_FALSE ;
784
+ return false ;
799
785
}
800
786
801
- ZEND_HASH_FOREACH_VAL (Z_ARRVAL_P (user_set ), user_signo ) {
802
- signo = zval_get_long (user_signo );
803
- if (sigaddset (& set , signo ) != 0 ) {
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 < 0 || tmp > INT_MAX ) {
798
+ zend_argument_value_error (1 , "signals must be between 0 and %d" , INT_MAX );
799
+ return false;
800
+ }
801
+
802
+ int signal_no = (int ) tmp ;
803
+ errno = 0 ;
804
+ if (sigaddset (set , signal_no ) != 0 ) {
804
805
PCNTL_G (last_error ) = errno ;
805
806
php_error_docref (NULL , E_WARNING , "%s" , strerror (errno ));
806
- RETURN_FALSE ;
807
+ return false ;
807
808
}
808
809
} ZEND_HASH_FOREACH_END ();
810
+ return true;
811
+ }
809
812
810
- if (timedwait ) {
811
- timeout .tv_sec = (time_t ) tv_sec ;
812
- timeout .tv_nsec = tv_nsec ;
813
- signo = sigtimedwait (& set , & siginfo , & timeout );
814
- } else {
815
- signo = sigwaitinfo (& set , & siginfo );
813
+ /* {{{ Synchronously wait for queued signals */
814
+ PHP_FUNCTION (pcntl_sigwaitinfo )
815
+ {
816
+ HashTable * user_set ;
817
+ /* Optional by-ref array of ints */
818
+ zval * user_siginfo = NULL ;
819
+
820
+ ZEND_PARSE_PARAMETERS_START (1 , 2 )
821
+ Z_PARAM_ARRAY_HT (user_set )
822
+ Z_PARAM_OPTIONAL
823
+ Z_PARAM_ZVAL (user_siginfo )
824
+ ZEND_PARSE_PARAMETERS_END ();
825
+
826
+ sigset_t set ;
827
+ bool status = php_pcntl_process_user_signal_infos (user_set , & set );
828
+ /* Some error occurred */
829
+ if (!status ) {
830
+ RETURN_FALSE ;
816
831
}
817
- if (signo == -1 && errno != EAGAIN ) {
832
+
833
+ errno = 0 ;
834
+ siginfo_t siginfo ;
835
+ int signal_no = sigwaitinfo (& set , & siginfo );
836
+ if (signal_no == -1 && errno != EAGAIN ) {
818
837
PCNTL_G (last_error ) = errno ;
819
838
php_error_docref (NULL , E_WARNING , "%s" , strerror (errno ));
839
+ // TODO BC Break, as -1 used to be returned?
840
+ // RETURN_FALSE;
820
841
}
821
842
822
- /*
823
- * sigtimedwait and sigwaitinfo can return 0 on success on some
824
- * platforms, e.g. NetBSD
825
- */
826
- if (!signo && siginfo .si_signo ) {
827
- signo = siginfo .si_signo ;
843
+ /* sigwaitinfo can return 0 on success on some platforms, e.g. NetBSD */
844
+ if (!signal_no && siginfo .si_signo ) {
845
+ signal_no = siginfo .si_signo ;
828
846
}
829
- pcntl_siginfo_to_zval (signo , & siginfo , user_siginfo );
830
- RETURN_LONG (signo );
831
- }
832
- /* }}} */
833
847
834
- /* {{{ Synchronously wait for queued signals */
835
- PHP_FUNCTION (pcntl_sigwaitinfo )
836
- {
837
- pcntl_sigwaitinfo (INTERNAL_FUNCTION_PARAM_PASSTHRU , 0 );
848
+ pcntl_siginfo_to_zval (signal_no , & siginfo , user_siginfo );
849
+
850
+ RETURN_LONG (signal_no );
838
851
}
839
852
/* }}} */
840
853
841
854
/* {{{ Wait for queued signals */
842
855
PHP_FUNCTION (pcntl_sigtimedwait )
843
856
{
844
- pcntl_sigwaitinfo (INTERNAL_FUNCTION_PARAM_PASSTHRU , 1 );
857
+ HashTable * user_set ;
858
+ /* Optional by-ref array of ints */
859
+ zval * user_siginfo = NULL ;
860
+ zend_long tv_sec = 0 ;
861
+ zend_long tv_nsec = 0 ;
862
+ struct timespec timeout ;
863
+
864
+ ZEND_PARSE_PARAMETERS_START (1 , 4 )
865
+ Z_PARAM_ARRAY_HT (user_set )
866
+ Z_PARAM_OPTIONAL
867
+ Z_PARAM_ZVAL (user_siginfo )
868
+ Z_PARAM_LONG (tv_sec )
869
+ Z_PARAM_LONG (tv_nsec )
870
+ ZEND_PARSE_PARAMETERS_END ();
871
+
872
+ sigset_t set ;
873
+ bool status = php_pcntl_process_user_signal_infos (user_set , & set );
874
+ /* Some error occurred */
875
+ if (!status ) {
876
+ RETURN_FALSE ;
877
+ }
878
+
879
+ errno = 0 ;
880
+ siginfo_t siginfo ;
881
+ timeout .tv_sec = (time_t ) tv_sec ;
882
+ timeout .tv_nsec = tv_nsec ;
883
+ int signal_no = sigtimedwait (& set , & siginfo , & timeout );
884
+ if (signal_no == -1 && errno != EAGAIN ) {
885
+ PCNTL_G (last_error ) = errno ;
886
+ php_error_docref (NULL , E_WARNING , "%s" , strerror (errno ));
887
+ // TODO BC Break, as -1 used to be returned?
888
+ // RETURN_FALSE;
889
+ }
890
+
891
+ /* sigtimedwait can return 0 on success on some platforms, e.g. NetBSD */
892
+ if (!signal_no && siginfo .si_signo ) {
893
+ signal_no = siginfo .si_signo ;
894
+ }
895
+
896
+ pcntl_siginfo_to_zval (signal_no , & siginfo , user_siginfo );
897
+
898
+ RETURN_LONG (signal_no );
845
899
}
846
900
/* }}} */
847
901
# endif
0 commit comments