bpo-33042: Fix pre-initialization sys module configuration (GH-6157) · python/cpython@bc77eff (original) (raw)

`@@ -2,6 +2,7 @@

`

2

2

`#include "pythread.h"

`

3

3

`#include <inttypes.h>

`

4

4

`#include <stdio.h>

`

``

5

`+

#include <wchar.h>

`

5

6

``

6

7

`/*********************************************************

`

7

8

` * Embedded interpreter tests that need a custom exe

`

`@@ -130,23 +131,89 @@ static int test_forced_io_encoding(void)

`

130

131

` * Test parts of the C-API that work before initialization

`

131

132

` *********************************************************/

`

132

133

``

``

134

`+

/* The pre-initialization tests tend to break by segfaulting, so explicitly

`

``

135

`+

`

``

136

`+

*/

`

``

137

`+

#define _Py_EMBED_PREINIT_CHECK(msg) \

`

``

138

`+

do {printf(msg); fflush(stdout);} while (0);

`

``

139

+

133

140

`static int test_pre_initialization_api(void)

`

134

141

`{

`

135

142

`/* Leading "./" ensures getpath.c can still find the standard library */

`

``

143

`+

_Py_EMBED_PREINIT_CHECK("Checking Py_DecodeLocale\n");

`

136

144

`wchar_t *program = Py_DecodeLocale("./spam", NULL);

`

137

145

`if (program == NULL) {

`

138

146

`fprintf(stderr, "Fatal error: cannot decode program name\n");

`

139

147

`return 1;

`

140

148

` }

`

``

149

`+

_Py_EMBED_PREINIT_CHECK("Checking Py_SetProgramName\n");

`

141

150

`Py_SetProgramName(program);

`

142

151

``

``

152

`+

_Py_EMBED_PREINIT_CHECK("Initializing interpreter\n");

`

143

153

`Py_Initialize();

`

``

154

`+

_Py_EMBED_PREINIT_CHECK("Check sys module contents\n");

`

``

155

`+

PyRun_SimpleString("import sys; "

`

``

156

`+

"print('sys.executable:', sys.executable)");

`

``

157

`+

_Py_EMBED_PREINIT_CHECK("Finalizing interpreter\n");

`

144

158

`Py_Finalize();

`

145

159

``

``

160

`+

_Py_EMBED_PREINIT_CHECK("Freeing memory allocated by Py_DecodeLocale\n");

`

146

161

`PyMem_RawFree(program);

`

147

162

`return 0;

`

148

163

`}

`

149

164

``

``

165

+

``

166

`+

/* bpo-33042: Ensure embedding apps can predefine sys module options */

`

``

167

`+

static int test_pre_initialization_sys_options(void)

`

``

168

`+

{

`

``

169

`+

/* We allocate a couple of the option dynamically, and then delete

`

``

170

`+

`

``

171

`+

`

``

172

`+

*/

`

``

173

`+

wchar_t *static_warnoption = L"once";

`

``

174

`+

wchar_t *static_xoption = L"also_not_an_option=2";

`

``

175

`+

size_t warnoption_len = wcslen(static_warnoption);

`

``

176

`+

size_t xoption_len = wcslen(static_xoption);

`

``

177

`+

wchar_t *dynamic_once_warnoption = calloc(warnoption_len+1, sizeof(wchar_t));

`

``

178

`+

wchar_t *dynamic_xoption = calloc(xoption_len+1, sizeof(wchar_t));

`

``

179

`+

wcsncpy(dynamic_once_warnoption, static_warnoption, warnoption_len+1);

`

``

180

`+

wcsncpy(dynamic_xoption, static_xoption, xoption_len+1);

`

``

181

+

``

182

`+

_Py_EMBED_PREINIT_CHECK("Checking PySys_AddWarnOption\n");

`

``

183

`+

PySys_AddWarnOption(L"default");

`

``

184

`+

_Py_EMBED_PREINIT_CHECK("Checking PySys_ResetWarnOptions\n");

`

``

185

`+

PySys_ResetWarnOptions();

`

``

186

`+

_Py_EMBED_PREINIT_CHECK("Checking PySys_AddWarnOption linked list\n");

`

``

187

`+

PySys_AddWarnOption(dynamic_once_warnoption);

`

``

188

`+

PySys_AddWarnOption(L"module");

`

``

189

`+

PySys_AddWarnOption(L"default");

`

``

190

`+

_Py_EMBED_PREINIT_CHECK("Checking PySys_AddXOption\n");

`

``

191

`+

PySys_AddXOption(L"not_an_option=1");

`

``

192

`+

PySys_AddXOption(dynamic_xoption);

`

``

193

+

``

194

`+

/* Delete the dynamic options early */

`

``

195

`+

free(dynamic_once_warnoption);

`

``

196

`+

dynamic_once_warnoption = NULL;

`

``

197

`+

free(dynamic_xoption);

`

``

198

`+

dynamic_xoption = NULL;

`

``

199

+

``

200

`+

_Py_EMBED_PREINIT_CHECK("Initializing interpreter\n");

`

``

201

`+

_testembed_Py_Initialize();

`

``

202

`+

_Py_EMBED_PREINIT_CHECK("Check sys module contents\n");

`

``

203

`+

PyRun_SimpleString("import sys; "

`

``

204

`+

"print('sys.warnoptions:', sys.warnoptions); "

`

``

205

`+

"print('sys._xoptions:', sys._xoptions); "

`

``

206

`+

"warnings = sys.modules['warnings']; "

`

``

207

`+

"latest_filters = [f[0] for f in warnings.filters[:3]]; "

`

``

208

`+

"print('warnings.filters[:3]:', latest_filters)");

`

``

209

`+

_Py_EMBED_PREINIT_CHECK("Finalizing interpreter\n");

`

``

210

`+

Py_Finalize();

`

``

211

+

``

212

`+

return 0;

`

``

213

`+

}

`

``

214

+

``

215

+

``

216

`+

/* bpo-20891: Avoid race condition when initialising the GIL */

`

150

217

`static void bpo20891_thread(void *lockp)

`

151

218

`{

`

152

219

`PyThread_type_lock lock = ((PyThread_type_lock)lockp);

`

`@@ -217,6 +284,7 @@ static struct TestCase TestCases[] = {

`

217

284

` { "forced_io_encoding", test_forced_io_encoding },

`

218

285

` { "repeated_init_and_subinterpreters", test_repeated_init_and_subinterpreters },

`

219

286

` { "pre_initialization_api", test_pre_initialization_api },

`

``

287

`+

{ "pre_initialization_sys_options", test_pre_initialization_sys_options },

`

220

288

` { "bpo20891", test_bpo20891 },

`

221

289

` { NULL, NULL }

`

222

290

`};

`

`@@ -232,13 +300,13 @@ int main(int argc, char *argv[])

`

232

300

``

233

301

`/* No match found, or no test name provided, so display usage */

`

234

302

`printf("Python " PY_VERSION " _testembed executable for embedded interpreter tests\n"

`

235

``

`-

"Normally executed via 'EmbeddingTests' in Lib/test/test_capi.py\n\n"

`

``

303

`+

"Normally executed via 'EmbeddingTests' in Lib/test/test_embed.py\n\n"

`

236

304

`"Usage: %s TESTNAME\n\nAll available tests:\n", argv[0]);

`

237

305

`for (struct TestCase *tc = TestCases; tc && tc->name; tc++) {

`

238

306

`printf(" %s\n", tc->name);

`

239

307

` }

`

240

308

``

241

``

`-

/* Non-zero exit code will cause test_capi.py tests to fail.

`

``

309

`+

/* Non-zero exit code will cause test_embed.py tests to fail.

`

242

310

` This is intentional. */

`

243

311

`return -1;

`

244

312

`}

`