summaryrefslogtreecommitdiff
path: root/Python/errors.c
diff options
context:
space:
mode:
authorGregory P. Smith <greg@krypto.org>2012-11-11 01:38:18 -0800
committerGregory P. Smith <greg@krypto.org>2012-11-11 01:38:18 -0800
commitf5a10551eefa79ea3e832d7ac757d9514164a319 (patch)
tree9a7c6bd7e15f70b1e39b2a8757f7250db2c7106f /Python/errors.c
parente95283e25478ce15d935cbee68d66964fc85490d (diff)
parent7072a6363abb71cbe03c17b918a3e5c6c4407c90 (diff)
downloadcpython-f5a10551eefa79ea3e832d7ac757d9514164a319.tar.gz
Fixes issue #16140: The subprocess module no longer double closes its
child subprocess.PIPE parent file descriptors on child error prior to exec(). This would lead to race conditions in multithreaded programs where another thread opened a file reusing the fd which was then closed out from beneath it by the errant second close.
Diffstat (limited to 'Python/errors.c')
-rw-r--r--Python/errors.c165
1 files changed, 129 insertions, 36 deletions
diff --git a/Python/errors.c b/Python/errors.c
index 5a9a624279..626b16e46f 100644
--- a/Python/errors.c
+++ b/Python/errors.c
@@ -320,6 +320,39 @@ PyErr_Clear(void)
PyErr_Restore(NULL, NULL, NULL);
}
+void
+PyErr_GetExcInfo(PyObject **p_type, PyObject **p_value, PyObject **p_traceback)
+{
+ PyThreadState *tstate = PyThreadState_GET();
+
+ *p_type = tstate->exc_type;
+ *p_value = tstate->exc_value;
+ *p_traceback = tstate->exc_traceback;
+
+ Py_XINCREF(*p_type);
+ Py_XINCREF(*p_value);
+ Py_XINCREF(*p_traceback);
+}
+
+void
+PyErr_SetExcInfo(PyObject *p_type, PyObject *p_value, PyObject *p_traceback)
+{
+ PyObject *oldtype, *oldvalue, *oldtraceback;
+ PyThreadState *tstate = PyThreadState_GET();
+
+ oldtype = tstate->exc_type;
+ oldvalue = tstate->exc_value;
+ oldtraceback = tstate->exc_traceback;
+
+ tstate->exc_type = p_type;
+ tstate->exc_value = p_value;
+ tstate->exc_traceback = p_traceback;
+
+ Py_XDECREF(oldtype);
+ Py_XDECREF(oldvalue);
+ Py_XDECREF(oldtraceback);
+}
+
/* Convenience functions to set a type error exception and return 0 */
int
@@ -341,11 +374,9 @@ PyObject *
PyErr_SetFromErrnoWithFilenameObject(PyObject *exc, PyObject *filenameObject)
{
PyObject *message;
- PyObject *v;
+ PyObject *v, *args;
int i = errno;
-#ifndef MS_WINDOWS
- char *s;
-#else
+#ifdef MS_WINDOWS
WCHAR *s_buf = NULL;
#endif /* Unix/Windows */
@@ -355,11 +386,14 @@ PyErr_SetFromErrnoWithFilenameObject(PyObject *exc, PyObject *filenameObject)
#endif
#ifndef MS_WINDOWS
- if (i == 0)
- s = "Error"; /* Sometimes errno didn't get set */
- else
- s = strerror(i);
- message = PyUnicode_DecodeUTF8(s, strlen(s), "ignore");
+ if (i != 0) {
+ char *s = strerror(i);
+ message = PyUnicode_DecodeLocale(s, "surrogateescape");
+ }
+ else {
+ /* Sometimes errno didn't get set */
+ message = PyUnicode_FromString("Error");
+ }
#else
if (i == 0)
message = PyUnicode_FromString("Error"); /* Sometimes errno didn't get set */
@@ -395,7 +429,7 @@ PyErr_SetFromErrnoWithFilenameObject(PyObject *exc, PyObject *filenameObject)
/* remove trailing cr/lf and dots */
while (len > 0 && (s_buf[len-1] <= L' ' || s_buf[len-1] == L'.'))
s_buf[--len] = L'\0';
- message = PyUnicode_FromUnicode(s_buf, len);
+ message = PyUnicode_FromWideChar(s_buf, len);
}
}
}
@@ -410,14 +444,18 @@ PyErr_SetFromErrnoWithFilenameObject(PyObject *exc, PyObject *filenameObject)
}
if (filenameObject != NULL)
- v = Py_BuildValue("(iOO)", i, message, filenameObject);
+ args = Py_BuildValue("(iOO)", i, message, filenameObject);
else
- v = Py_BuildValue("(iO)", i, message);
+ args = Py_BuildValue("(iO)", i, message);
Py_DECREF(message);
- if (v != NULL) {
- PyErr_SetObject(exc, v);
- Py_DECREF(v);
+ if (args != NULL) {
+ v = PyObject_Call(exc, args, NULL);
+ Py_DECREF(args);
+ if (v != NULL) {
+ PyErr_SetObject((PyObject *) Py_TYPE(v), v);
+ Py_DECREF(v);
+ }
}
#ifdef MS_WINDOWS
LocalFree(s_buf);
@@ -464,7 +502,7 @@ PyObject *PyErr_SetExcFromWindowsErrWithFilenameObject(
int len;
WCHAR *s_buf = NULL; /* Free via LocalFree */
PyObject *message;
- PyObject *v;
+ PyObject *args, *v;
DWORD err = (DWORD)ierr;
if (err==0) err = GetLastError();
len = FormatMessageW(
@@ -487,7 +525,7 @@ PyObject *PyErr_SetExcFromWindowsErrWithFilenameObject(
/* remove trailing cr/lf and dots */
while (len > 0 && (s_buf[len-1] <= L' ' || s_buf[len-1] == L'.'))
s_buf[--len] = L'\0';
- message = PyUnicode_FromUnicode(s_buf, len);
+ message = PyUnicode_FromWideChar(s_buf, len);
}
if (message == NULL)
@@ -496,15 +534,20 @@ PyObject *PyErr_SetExcFromWindowsErrWithFilenameObject(
return NULL;
}
- if (filenameObject != NULL)
- v = Py_BuildValue("(iOO)", err, message, filenameObject);
- else
- v = Py_BuildValue("(iO)", err, message);
+ if (filenameObject == NULL)
+ filenameObject = Py_None;
+ /* This is the constructor signature for passing a Windows error code.
+ The POSIX translation will be figured out by the constructor. */
+ args = Py_BuildValue("(iOOi)", 0, message, filenameObject, err);
Py_DECREF(message);
- if (v != NULL) {
- PyErr_SetObject(exc, v);
- Py_DECREF(v);
+ if (args != NULL) {
+ v = PyObject_Call(exc, args, NULL);
+ Py_DECREF(args);
+ if (v != NULL) {
+ PyErr_SetObject((PyObject *) Py_TYPE(v), v);
+ Py_DECREF(v);
+ }
}
LocalFree(s_buf);
return NULL;
@@ -575,6 +618,49 @@ PyObject *PyErr_SetFromWindowsErrWithUnicodeFilename(
}
#endif /* MS_WINDOWS */
+PyObject *
+PyErr_SetImportError(PyObject *msg, PyObject *name, PyObject *path)
+{
+ PyObject *args, *kwargs, *error;
+
+ if (msg == NULL)
+ return NULL;
+
+ args = PyTuple_New(1);
+ if (args == NULL)
+ return NULL;
+
+ kwargs = PyDict_New();
+ if (kwargs == NULL) {
+ Py_DECREF(args);
+ return NULL;
+ }
+
+ if (name == NULL) {
+ name = Py_None;
+ }
+
+ if (path == NULL) {
+ path = Py_None;
+ }
+
+ Py_INCREF(msg);
+ PyTuple_SET_ITEM(args, 0, msg);
+ PyDict_SetItemString(kwargs, "name", name);
+ PyDict_SetItemString(kwargs, "path", path);
+
+ error = PyObject_Call(PyExc_ImportError, args, kwargs);
+ if (error != NULL) {
+ PyErr_SetObject((PyObject *)Py_TYPE(error), error);
+ Py_DECREF(error);
+ }
+
+ Py_DECREF(args);
+ Py_DECREF(kwargs);
+
+ return NULL;
+}
+
void
_PyErr_BadInternalCall(const char *filename, int lineno)
{
@@ -656,7 +742,7 @@ PyErr_NewException(const char *name, PyObject *base, PyObject *dict)
if (bases == NULL)
goto failure;
}
- /* Create a real new-style class. */
+ /* Create a real class. */
result = PyObject_CallFunction((PyObject *)&PyType_Type, "sOO",
dot+1, bases, dict);
failure:
@@ -707,6 +793,7 @@ PyErr_NewExceptionWithDoc(const char *name, const char *doc,
void
PyErr_WriteUnraisable(PyObject *obj)
{
+ _Py_IDENTIFIER(__module__);
PyObject *f, *t, *v, *tb;
PyErr_Fetch(&t, &v, &tb);
f = PySys_GetObject("stderr");
@@ -723,7 +810,7 @@ PyErr_WriteUnraisable(PyObject *obj)
className = dot+1;
}
- moduleName = PyObject_GetAttrString(t, "__module__");
+ moduleName = _PyObject_GetAttrId(t, &PyId___module__);
if (moduleName == NULL)
PyFile_WriteString("<unknown>", f);
else {
@@ -774,6 +861,12 @@ void
PyErr_SyntaxLocationEx(const char *filename, int lineno, int col_offset)
{
PyObject *exc, *v, *tb, *tmp;
+ _Py_IDENTIFIER(filename);
+ _Py_IDENTIFIER(lineno);
+ _Py_IDENTIFIER(msg);
+ _Py_IDENTIFIER(offset);
+ _Py_IDENTIFIER(print_file_and_line);
+ _Py_IDENTIFIER(text);
/* add attributes for the line number and filename for the error */
PyErr_Fetch(&exc, &v, &tb);
@@ -784,7 +877,7 @@ PyErr_SyntaxLocationEx(const char *filename, int lineno, int col_offset)
if (tmp == NULL)
PyErr_Clear();
else {
- if (PyObject_SetAttrString(v, "lineno", tmp))
+ if (_PyObject_SetAttrId(v, &PyId_lineno, tmp))
PyErr_Clear();
Py_DECREF(tmp);
}
@@ -793,7 +886,7 @@ PyErr_SyntaxLocationEx(const char *filename, int lineno, int col_offset)
if (tmp == NULL)
PyErr_Clear();
else {
- if (PyObject_SetAttrString(v, "offset", tmp))
+ if (_PyObject_SetAttrId(v, &PyId_offset, tmp))
PyErr_Clear();
Py_DECREF(tmp);
}
@@ -803,35 +896,35 @@ PyErr_SyntaxLocationEx(const char *filename, int lineno, int col_offset)
if (tmp == NULL)
PyErr_Clear();
else {
- if (PyObject_SetAttrString(v, "filename", tmp))
+ if (_PyObject_SetAttrId(v, &PyId_filename, tmp))
PyErr_Clear();
Py_DECREF(tmp);
}
tmp = PyErr_ProgramText(filename, lineno);
if (tmp) {
- if (PyObject_SetAttrString(v, "text", tmp))
+ if (_PyObject_SetAttrId(v, &PyId_text, tmp))
PyErr_Clear();
Py_DECREF(tmp);
}
}
- if (PyObject_SetAttrString(v, "offset", Py_None)) {
+ if (_PyObject_SetAttrId(v, &PyId_offset, Py_None)) {
PyErr_Clear();
}
if (exc != PyExc_SyntaxError) {
- if (!PyObject_HasAttrString(v, "msg")) {
+ if (!_PyObject_HasAttrId(v, &PyId_msg)) {
tmp = PyObject_Str(v);
if (tmp) {
- if (PyObject_SetAttrString(v, "msg", tmp))
+ if (_PyObject_SetAttrId(v, &PyId_msg, tmp))
PyErr_Clear();
Py_DECREF(tmp);
} else {
PyErr_Clear();
}
}
- if (!PyObject_HasAttrString(v, "print_file_and_line")) {
- if (PyObject_SetAttrString(v, "print_file_and_line",
- Py_None))
+ if (!_PyObject_HasAttrId(v, &PyId_print_file_and_line)) {
+ if (_PyObject_SetAttrId(v, &PyId_print_file_and_line,
+ Py_None))
PyErr_Clear();
}
}