@@ -176,14 +176,6 @@ corresponding Unix manual entries for more information on calls.");
176176#else
177177/* Unix functions that the configure script doesn't check for */
178178#define HAVE_EXECV 1
179- /* bpo-32705: Current Android does not have posix_spawn
180- * Most likely posix_spawn will be available in next Android version (Android
181- * P, API 28). Need revisit then. See
182- * https://android-review.googlesource.com/c/platform/bionic/+/504842
183- **/
184- #ifndef __ANDROID__
185- #define HAVE_POSIX_SPAWN 1
186- #endif
187179#define HAVE_FORK 1
188180#if defined(__USLC__ ) && defined(__SCO_VERSION__ ) /* SCO UDK Compiler */
189181#define HAVE_FORK1 1
@@ -5139,17 +5131,22 @@ os_posix_spawn_impl(PyObject *module, path_t *path, PyObject *argv,
51395131/*[clinic end generated code: output=d023521f541c709c input=0ec9f1cfdc890be5]*/
51405132{
51415133 EXECV_CHAR * * argvlist = NULL ;
5142- EXECV_CHAR * * envlist ;
5134+ EXECV_CHAR * * envlist = NULL ;
5135+ posix_spawn_file_actions_t _file_actions ;
5136+ posix_spawn_file_actions_t * file_actionsp = NULL ;
51435137 Py_ssize_t argc , envc ;
5138+ PyObject * result = NULL ;
5139+ PyObject * seq = NULL ;
5140+
51445141
51455142 /* posix_spawn has three arguments: (path, argv, env), where
51465143 argv is a list or tuple of strings and env is a dictionary
51475144 like posix.environ. */
51485145
5149- if (!PySequence_Check (argv )){
5146+ if (!PySequence_Check (argv )) {
51505147 PyErr_SetString (PyExc_TypeError ,
51515148 "posix_spawn: argv must be a tuple or list" );
5152- goto fail ;
5149+ goto exit ;
51535150 }
51545151 argc = PySequence_Size (argv );
51555152 if (argc < 1 ) {
@@ -5160,50 +5157,47 @@ os_posix_spawn_impl(PyObject *module, path_t *path, PyObject *argv,
51605157 if (!PyMapping_Check (env )) {
51615158 PyErr_SetString (PyExc_TypeError ,
51625159 "posix_spawn: environment must be a mapping object" );
5163- goto fail ;
5160+ goto exit ;
51645161 }
51655162
51665163 argvlist = parse_arglist (argv , & argc );
51675164 if (argvlist == NULL ) {
5168- goto fail ;
5165+ goto exit ;
51695166 }
51705167 if (!argvlist [0 ][0 ]) {
51715168 PyErr_SetString (PyExc_ValueError ,
51725169 "posix_spawn: argv first element cannot be empty" );
5173- goto fail ;
5170+ goto exit ;
51745171 }
51755172
51765173 envlist = parse_envlist (env , & envc );
5177- if (envlist == NULL )
5178- goto fail ;
5174+ if (envlist == NULL ) {
5175+ goto exit ;
5176+ }
51795177
51805178 pid_t pid ;
5181- posix_spawn_file_actions_t * file_actionsp = NULL ;
5182- if (file_actions != NULL && file_actions != Py_None ){
5183- posix_spawn_file_actions_t _file_actions ;
5179+ if (file_actions != NULL && file_actions != Py_None ) {
51845180 if (posix_spawn_file_actions_init (& _file_actions ) != 0 ){
5185- PyErr_SetString (PyExc_TypeError ,
5181+ PyErr_SetString (PyExc_OSError ,
51865182 "Error initializing file actions" );
5187- goto fail ;
5183+ goto exit ;
51885184 }
51895185
5190-
51915186 file_actionsp = & _file_actions ;
51925187
5193-
5194- PyObject * seq = PySequence_Fast (file_actions , "file_actions must be a sequence" );
5195- if (seq == NULL ){
5196- goto fail ;
5188+ seq = PySequence_Fast (file_actions , "file_actions must be a sequence" );
5189+ if (seq == NULL ) {
5190+ goto exit ;
51975191 }
51985192 PyObject * file_actions_obj ;
51995193 PyObject * mode_obj ;
52005194
52015195 for (int i = 0 ; i < PySequence_Fast_GET_SIZE (seq ); ++ i ) {
52025196 file_actions_obj = PySequence_Fast_GET_ITEM (seq , i );
52035197
5204- if (!PySequence_Check (file_actions_obj ) | !PySequence_Size (file_actions_obj )){
5198+ if (!PySequence_Check (file_actions_obj ) | !PySequence_Size (file_actions_obj )) {
52055199 PyErr_SetString (PyExc_TypeError ,"Each file_action element must be a non empty sequence" );
5206- goto fail ;
5200+ goto exit ;
52075201 }
52085202
52095203
@@ -5215,83 +5209,103 @@ os_posix_spawn_impl(PyObject *module, path_t *path, PyObject *argv,
52155209 switch (mode ) {
52165210
52175211 case POSIX_SPAWN_OPEN :
5218- if (PySequence_Size (file_actions_obj ) != 5 ){
5212+ if (PySequence_Size (file_actions_obj ) != 5 ) {
52195213 PyErr_SetString (PyExc_TypeError ,"A open file_action object must have 5 elements" );
5220- goto fail ;
5214+ goto exit ;
52215215 }
52225216
52235217 long open_fd = PyLong_AsLong (PySequence_GetItem (file_actions_obj , 1 ));
52245218 if (PyErr_Occurred ()) {
5225- goto fail ;
5219+ goto exit ;
52265220 }
52275221 const char * open_path = PyUnicode_AsUTF8 (PySequence_GetItem (file_actions_obj , 2 ));
5228- if (open_path == NULL ){
5229- goto fail ;
5222+ if (open_path == NULL ) {
5223+ goto exit ;
52305224 }
52315225 long open_oflag = PyLong_AsLong (PySequence_GetItem (file_actions_obj , 3 ));
52325226 if (PyErr_Occurred ()) {
5233- goto fail ;
5227+ goto exit ;
52345228 }
52355229 long open_mode = PyLong_AsLong (PySequence_GetItem (file_actions_obj , 4 ));
52365230 if (PyErr_Occurred ()) {
5237- goto fail ;
5231+ goto exit ;
5232+ }
5233+ if (posix_spawn_file_actions_addopen (file_actionsp , open_fd , open_path , open_oflag , open_mode )) {
5234+ PyErr_SetString (PyExc_OSError ,"Failed to add open file action" );
5235+ goto exit ;
52385236 }
5239- posix_spawn_file_actions_addopen ( file_actionsp , open_fd , open_path , open_oflag , open_mode );
5237+
52405238 break ;
52415239
52425240 case POSIX_SPAWN_CLOSE :
52435241 if (PySequence_Size (file_actions_obj ) != 2 ){
52445242 PyErr_SetString (PyExc_TypeError ,"A close file_action object must have 2 elements" );
5245- goto fail ;
5243+ goto exit ;
52465244 }
52475245
52485246 long close_fd = PyLong_AsLong (PySequence_GetItem (file_actions_obj , 1 ));
52495247 if (PyErr_Occurred ()) {
5250- goto fail ;
5248+ goto exit ;
5249+ }
5250+ if (posix_spawn_file_actions_addclose (file_actionsp , close_fd )) {
5251+ PyErr_SetString (PyExc_OSError ,"Failed to add close file action" );
5252+ goto exit ;
52515253 }
5252- posix_spawn_file_actions_addclose (file_actionsp , close_fd );
52535254 break ;
52545255
52555256 case POSIX_SPAWN_DUP2 :
52565257 if (PySequence_Size (file_actions_obj ) != 3 ){
52575258 PyErr_SetString (PyExc_TypeError ,"A dup2 file_action object must have 3 elements" );
5258- goto fail ;
5259+ goto exit ;
52595260 }
52605261
52615262 long fd1 = PyLong_AsLong (PySequence_GetItem (file_actions_obj , 1 ));
52625263 if (PyErr_Occurred ()) {
5263- goto fail ;
5264+ goto exit ;
52645265 }
52655266 long fd2 = PyLong_AsLong (PySequence_GetItem (file_actions_obj , 2 ));
52665267 if (PyErr_Occurred ()) {
5267- goto fail ;
5268+ goto exit ;
5269+ }
5270+ if (posix_spawn_file_actions_adddup2 (file_actionsp , fd1 , fd2 )) {
5271+ PyErr_SetString (PyExc_OSError ,"Failed to add dup2 file action" );
5272+ goto exit ;
52685273 }
5269- posix_spawn_file_actions_adddup2 (file_actionsp , fd1 , fd2 );
52705274 break ;
52715275
52725276 default :
52735277 PyErr_SetString (PyExc_TypeError ,"Unknown file_actions identifier" );
5274- goto fail ;
5278+ goto exit ;
52755279 }
52765280 }
5277- Py_DECREF (seq );
5278- }
5281+ }
52795282
52805283 _Py_BEGIN_SUPPRESS_IPH
5281- posix_spawn (& pid , path -> narrow , file_actionsp , NULL , argvlist , envlist );
5282- return PyLong_FromPid (pid );
5284+ int err_code = posix_spawn (& pid , path -> narrow , file_actionsp , NULL , argvlist , envlist );
52835285 _Py_END_SUPPRESS_IPH
5286+ if (err_code ) {
5287+ PyErr_SetString (PyExc_OSError ,"posix_spawn call failed" );
5288+ goto exit ;
5289+ }
5290+ result = PyLong_FromPid (pid );
52845291
5285- path_error ( path );
5292+ exit :
52865293
5287- free_string_array ( envlist , envc );
5294+ Py_XDECREF ( seq );
52885295
5289- fail :
5296+ if (file_actionsp ) {
5297+ posix_spawn_file_actions_destroy (file_actionsp );
5298+ }
5299+
5300+ if (envlist ) {
5301+ free_string_array (envlist , envc );
5302+ }
52905303
52915304 if (argvlist ) {
52925305 free_string_array (argvlist , argc );
52935306 }
5294- return NULL ;
5307+
5308+ return result ;
52955309
52965310
52975311}
0 commit comments