bpo-20104: Fix leaks and errors in new os.posix_spawn (GH-5418) · python/cpython@0cd6bca (original) (raw)
`@@ -176,14 +176,6 @@ corresponding Unix manual entries for more information on calls.");
`
176
176
`#else
`
177
177
`/* Unix functions that the configure script doesn't check for */
`
178
178
`#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
``
`-
`
183
``
`-
**/
`
184
``
`-
#ifndef ANDROID
`
185
``
`-
#define HAVE_POSIX_SPAWN 1
`
186
``
`-
#endif
`
187
179
`#define HAVE_FORK 1
`
188
180
`#if defined(USLC) && defined(SCO_VERSION) /* SCO UDK Compiler */
`
189
181
`#define HAVE_FORK1 1
`
`@@ -5139,17 +5131,22 @@ os_posix_spawn_impl(PyObject *module, path_t *path, PyObject *argv,
`
5139
5131
`/[clinic end generated code: output=d023521f541c709c input=0ec9f1cfdc890be5]/
`
5140
5132
`{
`
5141
5133
`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;
`
5143
5137
`Py_ssize_t argc, envc;
`
``
5138
`+
PyObject* result = NULL;
`
``
5139
`+
PyObject* seq = NULL;
`
``
5140
+
5144
5141
``
5145
5142
`/* posix_spawn has three arguments: (path, argv, env), where
`
5146
5143
` argv is a list or tuple of strings and env is a dictionary
`
5147
5144
` like posix.environ. */
`
5148
5145
``
5149
``
`-
if (!PySequence_Check(argv)){
`
``
5146
`+
if (!PySequence_Check(argv)) {
`
5150
5147
`PyErr_SetString(PyExc_TypeError,
`
5151
5148
`"posix_spawn: argv must be a tuple or list");
`
5152
``
`-
goto fail;
`
``
5149
`+
goto exit;
`
5153
5150
` }
`
5154
5151
`argc = PySequence_Size(argv);
`
5155
5152
`if (argc < 1) {
`
`@@ -5160,50 +5157,47 @@ os_posix_spawn_impl(PyObject *module, path_t *path, PyObject *argv,
`
5160
5157
`if (!PyMapping_Check(env)) {
`
5161
5158
`PyErr_SetString(PyExc_TypeError,
`
5162
5159
`"posix_spawn: environment must be a mapping object");
`
5163
``
`-
goto fail;
`
``
5160
`+
goto exit;
`
5164
5161
` }
`
5165
5162
``
5166
5163
`argvlist = parse_arglist(argv, &argc);
`
5167
5164
`if (argvlist == NULL) {
`
5168
``
`-
goto fail;
`
``
5165
`+
goto exit;
`
5169
5166
` }
`
5170
5167
`if (!argvlist[0][0]) {
`
5171
5168
`PyErr_SetString(PyExc_ValueError,
`
5172
5169
`"posix_spawn: argv first element cannot be empty");
`
5173
``
`-
goto fail;
`
``
5170
`+
goto exit;
`
5174
5171
` }
`
5175
5172
``
5176
5173
`envlist = parse_envlist(env, &envc);
`
5177
``
`-
if (envlist == NULL)
`
5178
``
`-
goto fail;
`
``
5174
`+
if (envlist == NULL) {
`
``
5175
`+
goto exit;
`
``
5176
`+
}
`
5179
5177
``
5180
5178
`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) {
`
5184
5180
`if(posix_spawn_file_actions_init(&_file_actions) != 0){
`
5185
``
`-
PyErr_SetString(PyExc_TypeError,
`
``
5181
`+
PyErr_SetString(PyExc_OSError,
`
5186
5182
`"Error initializing file actions");
`
5187
``
`-
goto fail;
`
``
5183
`+
goto exit;
`
5188
5184
` }
`
5189
5185
``
5190
``
-
5191
5186
`file_actionsp = &_file_actions;
`
5192
5187
``
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;
`
5197
5191
` }
`
5198
5192
`PyObject* file_actions_obj;
`
5199
5193
`PyObject* mode_obj;
`
5200
5194
``
5201
5195
`for (int i = 0; i < PySequence_Fast_GET_SIZE(seq); ++i) {
`
5202
5196
`file_actions_obj = PySequence_Fast_GET_ITEM(seq, i);
`
5203
5197
``
5204
``
`-
if(!PySequence_Check(file_actions_obj) | !PySequence_Size(file_actions_obj)){
`
``
5198
`+
if(!PySequence_Check(file_actions_obj) | !PySequence_Size(file_actions_obj)) {
`
5205
5199
`PyErr_SetString(PyExc_TypeError,"Each file_action element must be a non empty sequence");
`
5206
``
`-
goto fail;
`
``
5200
`+
goto exit;
`
5207
5201
` }
`
5208
5202
``
5209
5203
``
`@@ -5215,83 +5209,103 @@ os_posix_spawn_impl(PyObject *module, path_t *path, PyObject *argv,
`
5215
5209
`switch(mode) {
`
5216
5210
``
5217
5211
`case POSIX_SPAWN_OPEN:
`
5218
``
`-
if(PySequence_Size(file_actions_obj) != 5){
`
``
5212
`+
if(PySequence_Size(file_actions_obj) != 5) {
`
5219
5213
`PyErr_SetString(PyExc_TypeError,"A open file_action object must have 5 elements");
`
5220
``
`-
goto fail;
`
``
5214
`+
goto exit;
`
5221
5215
` }
`
5222
5216
``
5223
5217
`long open_fd = PyLong_AsLong(PySequence_GetItem(file_actions_obj, 1));
`
5224
5218
`if(PyErr_Occurred()) {
`
5225
``
`-
goto fail;
`
``
5219
`+
goto exit;
`
5226
5220
` }
`
5227
5221
`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;
`
5230
5224
` }
`
5231
5225
`long open_oflag = PyLong_AsLong(PySequence_GetItem(file_actions_obj, 3));
`
5232
5226
`if(PyErr_Occurred()) {
`
5233
``
`-
goto fail;
`
``
5227
`+
goto exit;
`
5234
5228
` }
`
5235
5229
`long open_mode = PyLong_AsLong(PySequence_GetItem(file_actions_obj, 4));
`
5236
5230
`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;
`
5238
5236
` }
`
5239
``
`-
posix_spawn_file_actions_addopen(file_actionsp, open_fd, open_path, open_oflag, open_mode);
`
``
5237
+
5240
5238
`break;
`
5241
5239
``
5242
5240
`case POSIX_SPAWN_CLOSE:
`
5243
5241
`if(PySequence_Size(file_actions_obj) != 2){
`
5244
5242
`PyErr_SetString(PyExc_TypeError,"A close file_action object must have 2 elements");
`
5245
``
`-
goto fail;
`
``
5243
`+
goto exit;
`
5246
5244
` }
`
5247
5245
``
5248
5246
`long close_fd = PyLong_AsLong(PySequence_GetItem(file_actions_obj, 1));
`
5249
5247
`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;
`
5251
5253
` }
`
5252
``
`-
posix_spawn_file_actions_addclose(file_actionsp, close_fd);
`
5253
5254
`break;
`
5254
5255
``
5255
5256
`case POSIX_SPAWN_DUP2:
`
5256
5257
`if(PySequence_Size(file_actions_obj) != 3){
`
5257
5258
`PyErr_SetString(PyExc_TypeError,"A dup2 file_action object must have 3 elements");
`
5258
``
`-
goto fail;
`
``
5259
`+
goto exit;
`
5259
5260
` }
`
5260
5261
``
5261
5262
`long fd1 = PyLong_AsLong(PySequence_GetItem(file_actions_obj, 1));
`
5262
5263
`if(PyErr_Occurred()) {
`
5263
``
`-
goto fail;
`
``
5264
`+
goto exit;
`
5264
5265
` }
`
5265
5266
`long fd2 = PyLong_AsLong(PySequence_GetItem(file_actions_obj, 2));
`
5266
5267
`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;
`
5268
5273
` }
`
5269
``
`-
posix_spawn_file_actions_adddup2(file_actionsp, fd1, fd2);
`
5270
5274
`break;
`
5271
5275
``
5272
5276
`default:
`
5273
5277
`PyErr_SetString(PyExc_TypeError,"Unknown file_actions identifier");
`
5274
``
`-
goto fail;
`
``
5278
`+
goto exit;
`
5275
5279
` }
`
5276
5280
` }
`
5277
``
`-
Py_DECREF(seq);
`
5278
``
`-
}
`
``
5281
`+
}
`
5279
5282
``
5280
5283
`_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);
`
5283
5285
`_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);
`
5284
5291
``
5285
``
`-
path_error(path);
`
``
5292
`+
exit:
`
5286
5293
``
5287
``
`-
free_string_array(envlist, envc);
`
``
5294
`+
Py_XDECREF(seq);
`
5288
5295
``
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
`+
}
`
5290
5303
``
5291
5304
`if (argvlist) {
`
5292
5305
`free_string_array(argvlist, argc);
`
5293
5306
` }
`
5294
``
`-
return NULL;
`
``
5307
+
``
5308
`+
return result;
`
5295
5309
``
5296
5310
``
5297
5311
`}
`