7575
7676static struct PyModuleDef _posixsubprocessmodule ;
7777
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+
78100/* Convert ASCII to a positive int, no libc call. no overflow. -1 on error. */
79101static int
80102_pos_int_from_ascii (const char * name )
@@ -744,7 +766,7 @@ do_fork_exec(char *const exec_array[],
744766 assert (preexec_fn == Py_None );
745767
746768 pid = vfork ();
747- if (pid == -1 ) {
769+ if (pid == ( pid_t ) - 1 ) {
748770 /* If vfork() fails, fall back to using fork(). When it isn't
749771 * allowed in a process by the kernel, vfork can return -1
750772 * with errno EINVAL. https://bugs.python.org/issue47151. */
@@ -784,44 +806,81 @@ do_fork_exec(char *const exec_array[],
784806 return 0 ; /* Dead code to avoid a potential compiler warning. */
785807}
786808
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]*/
787858
788859static 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]*/
790872{
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 ;
795874 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 ;
802875 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 ;
806878 pid_t pid = -1 ;
807879 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 ;
810882 int need_after_fork = 0 ;
811883 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 ;
825884
826885 PyInterpreterState * interp = PyInterpreterState_Get ();
827886 if ((preexec_fn != Py_None ) && (interp != PyInterpreterState_Main ())) {
@@ -844,7 +903,7 @@ subprocess_fork_exec(PyObject *module, PyObject *args)
844903 need_to_reenable_gc = PyGC_Disable ();
845904 }
846905
847- exec_array = _PySequence_BytesToCharpArray (executable_list );
906+ char * const * exec_array = _PySequence_BytesToCharpArray (executable_list );
848907 if (!exec_array )
849908 goto cleanup ;
850909
@@ -862,7 +921,7 @@ subprocess_fork_exec(PyObject *module, PyObject *args)
862921 converted_args = PyTuple_New (num_args );
863922 if (converted_args == NULL )
864923 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 ) {
866925 PyObject * borrowed_arg , * converted_arg ;
867926 if (PySequence_Fast_GET_SIZE (fast_args ) != num_args ) {
868927 PyErr_SetString (PyExc_RuntimeError , "args changed during iteration" );
@@ -891,8 +950,6 @@ subprocess_fork_exec(PyObject *module, PyObject *args)
891950 if (PyUnicode_FSConverter (cwd_obj , & cwd_obj2 ) == 0 )
892951 goto cleanup ;
893952 cwd = PyBytes_AsString (cwd_obj2 );
894- } else {
895- cwd = NULL ;
896953 }
897954
898955 if (extra_groups_packed != Py_None ) {
@@ -1019,7 +1076,7 @@ subprocess_fork_exec(PyObject *module, PyObject *args)
10191076 py_fds_to_keep , preexec_fn , preexec_fn_args_tuple );
10201077
10211078 /* Parent (original) process */
1022- if (pid == -1 ) {
1079+ if (pid == ( pid_t ) - 1 ) {
10231080 /* Capture errno for the exception. */
10241081 saved_errno = errno ;
10251082 }
@@ -1068,47 +1125,17 @@ subprocess_fork_exec(PyObject *module, PyObject *args)
10681125 if (need_to_reenable_gc ) {
10691126 PyGC_Enable ();
10701127 }
1071- Py_XDECREF (gc_module );
10721128
10731129 return pid == -1 ? NULL : PyLong_FromPid (pid );
10741130}
10751131
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-
11051132/* module level code ********************************************************/
11061133
11071134PyDoc_STRVAR (module_doc ,
11081135"A POSIX helper for the subprocess module." );
11091136
11101137static PyMethodDef module_methods [] = {
1111- { "fork_exec" , subprocess_fork_exec , METH_VARARGS , subprocess_fork_exec_doc },
1138+ SUBPROCESS_FORK_EXEC_METHODDEF
11121139 {NULL , NULL } /* sentinel */
11131140};
11141141
0 commit comments