75
75
76
76
static struct PyModuleDef _posixsubprocessmodule ;
77
77
78
+ /*[clinic input]
79
+ module _posixsubprocess
80
+ [clinic start generated code]*/
81
+ /*[clinic end generated code: output=da39a3ee5e6b4b0d input=c62211df27cf7334]*/
82
+
83
+ /*[python input]
84
+ class pid_t_converter(CConverter):
85
+ type = 'pid_t'
86
+ format_unit = '" _Py_PARSE_PID "'
87
+
88
+ def parse_arg(self, argname, displayname):
89
+ return """
90
+ {paramname} = PyLong_AsPid({argname});
91
+ if ({paramname} == -1 && PyErr_Occurred()) {{{{
92
+ goto exit;
93
+ }}}}
94
+ """.format(argname=argname, paramname=self.parser_name)
95
+ [python start generated code]*/
96
+ /*[python end generated code: output=da39a3ee5e6b4b0d input=5af1c116d56cbb5a]*/
97
+
98
+ #include "clinic/_posixsubprocess.c.h"
99
+
78
100
/* Convert ASCII to a positive int, no libc call. no overflow. -1 on error. */
79
101
static int
80
102
_pos_int_from_ascii (const char * name )
@@ -744,7 +766,7 @@ do_fork_exec(char *const exec_array[],
744
766
assert (preexec_fn == Py_None );
745
767
746
768
pid = vfork ();
747
- if (pid == -1 ) {
769
+ if (pid == ( pid_t ) - 1 ) {
748
770
/* If vfork() fails, fall back to using fork(). When it isn't
749
771
* allowed in a process by the kernel, vfork can return -1
750
772
* with errno EINVAL. https://bugs.python.org/issue47151. */
@@ -784,44 +806,81 @@ do_fork_exec(char *const exec_array[],
784
806
return 0 ; /* Dead code to avoid a potential compiler warning. */
785
807
}
786
808
809
+ /*[clinic input]
810
+ _posixsubprocess.fork_exec as subprocess_fork_exec
811
+ args as process_args: object
812
+ executable_list: object
813
+ close_fds: bool
814
+ pass_fds as py_fds_to_keep: object(subclass_of='&PyTuple_Type')
815
+ cwd as cwd_obj: object
816
+ env as env_list: object
817
+ p2cread: int
818
+ p2cwrite: int
819
+ c2pread: int
820
+ c2pwrite: int
821
+ errread: int
822
+ errwrite: int
823
+ errpipe_read: int
824
+ errpipe_write: int
825
+ restore_signals: bool
826
+ call_setsid: bool
827
+ pgid_to_set: pid_t
828
+ gid as gid_object: object
829
+ extra_groups as extra_groups_packed: object
830
+ uid as uid_object: object
831
+ child_umask: int
832
+ preexec_fn: object
833
+ allow_vfork: bool
834
+ /
835
+
836
+ Spawn a fresh new child process.
837
+
838
+ Fork a child process, close parent file descriptors as appropriate in the
839
+ child and duplicate the few that are needed before calling exec() in the
840
+ child process.
841
+
842
+ If close_fds is True, close file descriptors 3 and higher, except those listed
843
+ in the sorted tuple pass_fds.
844
+
845
+ The preexec_fn, if supplied, will be called immediately before closing file
846
+ descriptors and exec.
847
+
848
+ WARNING: preexec_fn is NOT SAFE if your application uses threads.
849
+ It may trigger infrequent, difficult to debug deadlocks.
850
+
851
+ If an error occurs in the child process before the exec, it is
852
+ serialized and written to the errpipe_write fd per subprocess.py.
853
+
854
+ Returns: the child process's PID.
855
+
856
+ Raises: Only on an error in the parent process.
857
+ [clinic start generated code]*/
787
858
788
859
static PyObject *
789
- subprocess_fork_exec (PyObject * module , PyObject * args )
860
+ subprocess_fork_exec_impl (PyObject * module , PyObject * process_args ,
861
+ PyObject * executable_list , int close_fds ,
862
+ PyObject * py_fds_to_keep , PyObject * cwd_obj ,
863
+ PyObject * env_list , int p2cread , int p2cwrite ,
864
+ int c2pread , int c2pwrite , int errread ,
865
+ int errwrite , int errpipe_read , int errpipe_write ,
866
+ int restore_signals , int call_setsid ,
867
+ pid_t pgid_to_set , PyObject * gid_object ,
868
+ PyObject * extra_groups_packed ,
869
+ PyObject * uid_object , int child_umask ,
870
+ PyObject * preexec_fn , int allow_vfork )
871
+ /*[clinic end generated code: output=7ee4f6ee5cf22b5b input=51757287ef266ffa]*/
790
872
{
791
- PyObject * gc_module = NULL ;
792
- PyObject * executable_list , * py_fds_to_keep ;
793
- PyObject * env_list , * preexec_fn ;
794
- PyObject * process_args , * converted_args = NULL , * fast_args = NULL ;
873
+ PyObject * converted_args = NULL , * fast_args = NULL ;
795
874
PyObject * preexec_fn_args_tuple = NULL ;
796
- PyObject * extra_groups_packed ;
797
- PyObject * uid_object , * gid_object ;
798
- int p2cread , p2cwrite , c2pread , c2pwrite , errread , errwrite ;
799
- int errpipe_read , errpipe_write , close_fds , restore_signals ;
800
- int call_setsid ;
801
- pid_t pgid_to_set = -1 ;
802
875
gid_t * extra_groups = NULL ;
803
- int child_umask ;
804
- PyObject * cwd_obj , * cwd_obj2 = NULL ;
805
- const char * cwd ;
876
+ PyObject * cwd_obj2 = NULL ;
877
+ const char * cwd = NULL ;
806
878
pid_t pid = -1 ;
807
879
int need_to_reenable_gc = 0 ;
808
- char * const * exec_array , * const * argv = NULL , * const * envp = NULL ;
809
- Py_ssize_t arg_num , extra_group_size = 0 ;
880
+ char * const * argv = NULL , * const * envp = NULL ;
881
+ Py_ssize_t extra_group_size = 0 ;
810
882
int need_after_fork = 0 ;
811
883
int saved_errno = 0 ;
812
- int allow_vfork ;
813
-
814
- if (!PyArg_ParseTuple (
815
- args , "OOpO!OOiiiiiiiipp" _Py_PARSE_PID "OOOiOp:fork_exec" ,
816
- & process_args , & executable_list ,
817
- & close_fds , & PyTuple_Type , & py_fds_to_keep ,
818
- & cwd_obj , & env_list ,
819
- & p2cread , & p2cwrite , & c2pread , & c2pwrite ,
820
- & errread , & errwrite , & errpipe_read , & errpipe_write ,
821
- & restore_signals , & call_setsid , & pgid_to_set ,
822
- & gid_object , & extra_groups_packed , & uid_object , & child_umask ,
823
- & preexec_fn , & allow_vfork ))
824
- return NULL ;
825
884
826
885
PyInterpreterState * interp = PyInterpreterState_Get ();
827
886
if ((preexec_fn != Py_None ) && (interp != PyInterpreterState_Main ())) {
@@ -844,7 +903,7 @@ subprocess_fork_exec(PyObject *module, PyObject *args)
844
903
need_to_reenable_gc = PyGC_Disable ();
845
904
}
846
905
847
- exec_array = _PySequence_BytesToCharpArray (executable_list );
906
+ char * const * exec_array = _PySequence_BytesToCharpArray (executable_list );
848
907
if (!exec_array )
849
908
goto cleanup ;
850
909
@@ -862,7 +921,7 @@ subprocess_fork_exec(PyObject *module, PyObject *args)
862
921
converted_args = PyTuple_New (num_args );
863
922
if (converted_args == NULL )
864
923
goto cleanup ;
865
- for (arg_num = 0 ; arg_num < num_args ; ++ arg_num ) {
924
+ for (Py_ssize_t arg_num = 0 ; arg_num < num_args ; ++ arg_num ) {
866
925
PyObject * borrowed_arg , * converted_arg ;
867
926
if (PySequence_Fast_GET_SIZE (fast_args ) != num_args ) {
868
927
PyErr_SetString (PyExc_RuntimeError , "args changed during iteration" );
@@ -891,8 +950,6 @@ subprocess_fork_exec(PyObject *module, PyObject *args)
891
950
if (PyUnicode_FSConverter (cwd_obj , & cwd_obj2 ) == 0 )
892
951
goto cleanup ;
893
952
cwd = PyBytes_AsString (cwd_obj2 );
894
- } else {
895
- cwd = NULL ;
896
953
}
897
954
898
955
if (extra_groups_packed != Py_None ) {
@@ -1019,7 +1076,7 @@ subprocess_fork_exec(PyObject *module, PyObject *args)
1019
1076
py_fds_to_keep , preexec_fn , preexec_fn_args_tuple );
1020
1077
1021
1078
/* Parent (original) process */
1022
- if (pid == -1 ) {
1079
+ if (pid == ( pid_t ) - 1 ) {
1023
1080
/* Capture errno for the exception. */
1024
1081
saved_errno = errno ;
1025
1082
}
@@ -1068,47 +1125,17 @@ subprocess_fork_exec(PyObject *module, PyObject *args)
1068
1125
if (need_to_reenable_gc ) {
1069
1126
PyGC_Enable ();
1070
1127
}
1071
- Py_XDECREF (gc_module );
1072
1128
1073
1129
return pid == -1 ? NULL : PyLong_FromPid (pid );
1074
1130
}
1075
1131
1076
-
1077
- PyDoc_STRVAR (subprocess_fork_exec_doc ,
1078
- "fork_exec(args, executable_list, close_fds, pass_fds, cwd, env,\n\
1079
- p2cread, p2cwrite, c2pread, c2pwrite,\n\
1080
- errread, errwrite, errpipe_read, errpipe_write,\n\
1081
- restore_signals, call_setsid, pgid_to_set,\n\
1082
- gid, extra_groups, uid,\n\
1083
- preexec_fn)\n\
1084
- \n\
1085
- Forks a child process, closes parent file descriptors as appropriate in the\n\
1086
- child and dups the few that are needed before calling exec() in the child\n\
1087
- process.\n\
1088
- \n\
1089
- If close_fds is true, close file descriptors 3 and higher, except those listed\n\
1090
- in the sorted tuple pass_fds.\n\
1091
- \n\
1092
- The preexec_fn, if supplied, will be called immediately before closing file\n\
1093
- descriptors and exec.\n\
1094
- WARNING: preexec_fn is NOT SAFE if your application uses threads.\n\
1095
- It may trigger infrequent, difficult to debug deadlocks.\n\
1096
- \n\
1097
- If an error occurs in the child process before the exec, it is\n\
1098
- serialized and written to the errpipe_write fd per subprocess.py.\n\
1099
- \n\
1100
- Returns: the child process's PID.\n\
1101
- \n\
1102
- Raises: Only on an error in the parent process.\n\
1103
- " );
1104
-
1105
1132
/* module level code ********************************************************/
1106
1133
1107
1134
PyDoc_STRVAR (module_doc ,
1108
1135
"A POSIX helper for the subprocess module." );
1109
1136
1110
1137
static PyMethodDef module_methods [] = {
1111
- { "fork_exec" , subprocess_fork_exec , METH_VARARGS , subprocess_fork_exec_doc },
1138
+ SUBPROCESS_FORK_EXEC_METHODDEF
1112
1139
{NULL , NULL } /* sentinel */
1113
1140
};
1114
1141
0 commit comments