Commit 29f84381 authored by Benjamin Peterson's avatar Benjamin Peterson

merge heads

parents ab3c1c19 709176f1
...@@ -385,7 +385,7 @@ Glossary ...@@ -385,7 +385,7 @@ Glossary
:meth:`str.lower` method can serve as a key function for case insensitive :meth:`str.lower` method can serve as a key function for case insensitive
sorts. Alternatively, an ad-hoc key function can be built from a sorts. Alternatively, an ad-hoc key function can be built from a
:keyword:`lambda` expression such as ``lambda r: (r[0], r[2])``. Also, :keyword:`lambda` expression such as ``lambda r: (r[0], r[2])``. Also,
the :mod:`operator` module provides three key function constuctors: the :mod:`operator` module provides three key function constructors:
:func:`~operator.attrgetter`, :func:`~operator.itemgetter`, and :func:`~operator.attrgetter`, :func:`~operator.itemgetter`, and
:func:`~operator.methodcaller`. See the :ref:`Sorting HOW TO :func:`~operator.methodcaller`. See the :ref:`Sorting HOW TO
<sortinghowto>` for examples of how to create and use key functions. <sortinghowto>` for examples of how to create and use key functions.
......
...@@ -1642,8 +1642,8 @@ Argument groups ...@@ -1642,8 +1642,8 @@ Argument groups
--bar BAR bar help --bar BAR bar help
Note that any arguments not your user defined groups will end up back in the Note that any arguments not in your user-defined groups will end up back
usual "positional arguments" and "optional arguments" sections. in the usual "positional arguments" and "optional arguments" sections.
Mutual exclusion Mutual exclusion
...@@ -1833,9 +1833,10 @@ A partial upgrade path from :mod:`optparse` to :mod:`argparse`: ...@@ -1833,9 +1833,10 @@ A partial upgrade path from :mod:`optparse` to :mod:`argparse`:
* Replace all :meth:`optparse.OptionParser.add_option` calls with * Replace all :meth:`optparse.OptionParser.add_option` calls with
:meth:`ArgumentParser.add_argument` calls. :meth:`ArgumentParser.add_argument` calls.
* Replace ``options, args = parser.parse_args()`` with ``args = * Replace ``(options, args) = parser.parse_args()`` with ``args =
parser.parse_args()`` and add additional :meth:`ArgumentParser.add_argument` parser.parse_args()`` and add additional :meth:`ArgumentParser.add_argument`
calls for the positional arguments. calls for the positional arguments. Keep in mind that what was previously
called ``options``, now in :mod:`argparse` context is called ``args``.
* Replace callback actions and the ``callback_*`` keyword arguments with * Replace callback actions and the ``callback_*`` keyword arguments with
``type`` or ``action`` arguments. ``type`` or ``action`` arguments.
......
...@@ -654,7 +654,7 @@ event of a certain severity or greater is seen. ...@@ -654,7 +654,7 @@ event of a certain severity or greater is seen.
:class:`BufferingHandler`, which is an abstract class. This buffers logging :class:`BufferingHandler`, which is an abstract class. This buffers logging
records in memory. Whenever each record is added to the buffer, a check is made records in memory. Whenever each record is added to the buffer, a check is made
by calling :meth:`shouldFlush` to see if the buffer should be flushed. If it by calling :meth:`shouldFlush` to see if the buffer should be flushed. If it
should, then :meth:`flush` is expected to do the needful. should, then :meth:`flush` is expected to do the flushing.
.. class:: BufferingHandler(capacity) .. class:: BufferingHandler(capacity)
......
...@@ -5,46 +5,58 @@ ...@@ -5,46 +5,58 @@
:synopsis: Set handlers for asynchronous events. :synopsis: Set handlers for asynchronous events.
This module provides mechanisms to use signal handlers in Python. Some general This module provides mechanisms to use signal handlers in Python.
rules for working with signals and their handlers:
* A handler for a particular signal, once set, remains installed until it is General rules
explicitly reset (Python emulates the BSD style interface regardless of the -------------
underlying implementation), with the exception of the handler for
:const:`SIGCHLD`, which follows the underlying implementation. The :func:`signal.signal` function allows to define custom handlers to be
executed when a signal is received. A small number of default handlers are
* There is no way to "block" signals temporarily from critical sections (since installed: :const:`SIGPIPE` is ignored (so write errors on pipes and sockets
this is not supported by all Unix flavors). can be reported as ordinary Python exceptions) and :const:`SIGINT` is
translated into a :exc:`KeyboardInterrupt` exception.
* Although Python signal handlers are called asynchronously as far as the Python
user is concerned, they can only occur between the "atomic" instructions of the A handler for a particular signal, once set, remains installed until it is
Python interpreter. This means that signals arriving during long calculations explicitly reset (Python emulates the BSD style interface regardless of the
implemented purely in C (such as regular expression matches on large bodies of underlying implementation), with the exception of the handler for
text) may be delayed for an arbitrary amount of time. :const:`SIGCHLD`, which follows the underlying implementation.
* When a signal arrives during an I/O operation, it is possible that the I/O There is no way to "block" signals temporarily from critical sections (since
operation raises an exception after the signal handler returns. This is this is not supported by all Unix flavors).
dependent on the underlying Unix system's semantics regarding interrupted system
calls.
Execution of Python signal handlers
* Because the C signal handler always returns, it makes little sense to catch ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
synchronous errors like :const:`SIGFPE` or :const:`SIGSEGV`.
A Python signal handler does not get executed inside the low-level (C) signal
* Python installs a small number of signal handlers by default: :const:`SIGPIPE` handler. Instead, the low-level signal handler sets a flag which tells the
is ignored (so write errors on pipes and sockets can be reported as ordinary :term:`virtual machine` to execute the corresponding Python signal handler
Python exceptions) and :const:`SIGINT` is translated into a at a later point(for example at the next :term:`bytecode` instruction).
:exc:`KeyboardInterrupt` exception. All of these can be overridden. This has consequences:
* Some care must be taken if both signals and threads are used in the same * It makes little sense to catch synchronous errors like :const:`SIGFPE` or
program. The fundamental thing to remember in using signals and threads :const:`SIGSEGV`.
simultaneously is: always perform :func:`signal` operations in the main thread
of execution. Any thread can perform an :func:`alarm`, :func:`getsignal`, * A long-running calculation implemented purely in C (such as regular
:func:`pause`, :func:`setitimer` or :func:`getitimer`; only the main thread expression matching on a large body of text) may run uninterrupted for an
can set a new signal handler, and the main thread will be the only one to arbitrary amount of time, regardless of any signals received. The Python
receive signals (this is enforced by the Python :mod:`signal` module, even signal handlers will be called when the calculation finishes.
if the underlying thread implementation supports sending signals to
individual threads). This means that signals can't be used as a means of
inter-thread communication. Use locks instead. Signals and threads
^^^^^^^^^^^^^^^^^^^
Python signal handlers are always executed in the main Python thread,
even if the signal was received in another thread. This means that signals
can't be used as a means of inter-thread communication. You can use
the synchronization primitives from the :mod:`threading` module instead.
Besides, only the main thread is allowed to set a new signal handler.
Module contents
---------------
The variables defined in the :mod:`signal` module are: The variables defined in the :mod:`signal` module are:
......
...@@ -78,7 +78,8 @@ Priority levels (high to low): ...@@ -78,7 +78,8 @@ Priority levels (high to low):
Facilities: Facilities:
:const:`LOG_KERN`, :const:`LOG_USER`, :const:`LOG_MAIL`, :const:`LOG_DAEMON`, :const:`LOG_KERN`, :const:`LOG_USER`, :const:`LOG_MAIL`, :const:`LOG_DAEMON`,
:const:`LOG_AUTH`, :const:`LOG_LPR`, :const:`LOG_NEWS`, :const:`LOG_UUCP`, :const:`LOG_AUTH`, :const:`LOG_LPR`, :const:`LOG_NEWS`, :const:`LOG_UUCP`,
:const:`LOG_CRON` and :const:`LOG_LOCAL0` to :const:`LOG_LOCAL7`. :const:`LOG_CRON`, :const:`LOG_SYSLOG` and :const:`LOG_LOCAL0` to
:const:`LOG_LOCAL7`.
Log options: Log options:
:const:`LOG_PID`, :const:`LOG_CONS`, :const:`LOG_NDELAY`, :const:`LOG_NOWAIT` :const:`LOG_PID`, :const:`LOG_CONS`, :const:`LOG_NDELAY`, :const:`LOG_NOWAIT`
......
...@@ -640,7 +640,7 @@ This is the output of running the example above in verbose mode: :: ...@@ -640,7 +640,7 @@ This is the output of running the example above in verbose mode: ::
Classes can be skipped just like methods: :: Classes can be skipped just like methods: ::
@skip("showing class skipping") @unittest.skip("showing class skipping")
class MySkippedTestCase(unittest.TestCase): class MySkippedTestCase(unittest.TestCase):
def test_not_run(self): def test_not_run(self):
pass pass
......
...@@ -137,6 +137,8 @@ for the controller classes, all defined in this module. ...@@ -137,6 +137,8 @@ for the controller classes, all defined in this module.
+-----------------------+-----------------------------------------+-------+ +-----------------------+-----------------------------------------+-------+
| ``'macosx'`` | :class:`MacOSX('default')` | \(4) | | ``'macosx'`` | :class:`MacOSX('default')` | \(4) |
+-----------------------+-----------------------------------------+-------+ +-----------------------+-----------------------------------------+-------+
| ``'safari'`` | :class:`MacOSX('safari')` | \(4) |
+-----------------------+-----------------------------------------+-------+
Notes: Notes:
......
...@@ -112,12 +112,14 @@ class _AllCompletedWaiter(_Waiter): ...@@ -112,12 +112,14 @@ class _AllCompletedWaiter(_Waiter):
def __init__(self, num_pending_calls, stop_on_exception): def __init__(self, num_pending_calls, stop_on_exception):
self.num_pending_calls = num_pending_calls self.num_pending_calls = num_pending_calls
self.stop_on_exception = stop_on_exception self.stop_on_exception = stop_on_exception
self.lock = threading.Lock()
super().__init__() super().__init__()
def _decrement_pending_calls(self): def _decrement_pending_calls(self):
self.num_pending_calls -= 1 with self.lock:
if not self.num_pending_calls: self.num_pending_calls -= 1
self.event.set() if not self.num_pending_calls:
self.event.set()
def add_result(self, future): def add_result(self, future):
super().add_result(future) super().add_result(future)
......
What's New in IDLE 3.2.3? What's New in IDLE 3.2.3?
========================= =========================
- Issue #14409: IDLE now properly executes commands in the Shell window
when it cannot read the normal config files on startup and
has to use the built-in default key bindings.
There was previously a bug in one of the defaults.
- Issue #3573: IDLE hangs when passing invalid command line args - Issue #3573: IDLE hangs when passing invalid command line args
(directory(ies) instead of file(s)). (directory(ies) instead of file(s)).
......
...@@ -595,7 +595,7 @@ class IdleConf: ...@@ -595,7 +595,7 @@ class IdleConf:
'<<replace>>': ['<Control-h>'], '<<replace>>': ['<Control-h>'],
'<<goto-line>>': ['<Alt-g>'], '<<goto-line>>': ['<Alt-g>'],
'<<smart-backspace>>': ['<Key-BackSpace>'], '<<smart-backspace>>': ['<Key-BackSpace>'],
'<<newline-and-indent>>': ['<Key-Return> <Key-KP_Enter>'], '<<newline-and-indent>>': ['<Key-Return>', '<Key-KP_Enter>'],
'<<smart-indent>>': ['<Key-Tab>'], '<<smart-indent>>': ['<Key-Tab>'],
'<<indent-region>>': ['<Control-Key-bracketright>'], '<<indent-region>>': ['<Control-Key-bracketright>'],
'<<dedent-region>>': ['<Control-Key-bracketleft>'], '<<dedent-region>>': ['<Control-Key-bracketleft>'],
......
...@@ -519,11 +519,16 @@ class SocketHandler(logging.Handler): ...@@ -519,11 +519,16 @@ class SocketHandler(logging.Handler):
""" """
ei = record.exc_info ei = record.exc_info
if ei: if ei:
dummy = self.format(record) # just to get traceback text into record.exc_text # just to get traceback text into record.exc_text ...
record.exc_info = None # to avoid Unpickleable error dummy = self.format(record)
s = pickle.dumps(record.__dict__, 1) # See issue #14436: If msg or args are objects, they may not be
if ei: # available on the receiving end. So we convert the msg % args
record.exc_info = ei # for next handler # to a string, save it as msg and zap the args.
d = dict(record.__dict__)
d['msg'] = record.getMessage()
d['args'] = None
d['exc_info'] = None
s = pickle.dumps(d, 1)
slen = struct.pack(">L", len(s)) slen = struct.pack(">L", len(s))
return slen + s return slen + s
......
...@@ -94,6 +94,13 @@ def arbitrary_address(family): ...@@ -94,6 +94,13 @@ def arbitrary_address(family):
else: else:
raise ValueError('unrecognized family') raise ValueError('unrecognized family')
def _validate_family(family):
'''
Checks if the family is valid for the current environment.
'''
if sys.platform != 'win32' and family == 'AF_PIPE':
raise ValueError('Family %s is not recognized.' % family)
def address_type(address): def address_type(address):
''' '''
...@@ -126,6 +133,7 @@ class Listener(object): ...@@ -126,6 +133,7 @@ class Listener(object):
or default_family or default_family
address = address or arbitrary_address(family) address = address or arbitrary_address(family)
_validate_family(family)
if family == 'AF_PIPE': if family == 'AF_PIPE':
self._listener = PipeListener(address, backlog) self._listener = PipeListener(address, backlog)
else: else:
...@@ -163,6 +171,7 @@ def Client(address, family=None, authkey=None): ...@@ -163,6 +171,7 @@ def Client(address, family=None, authkey=None):
Returns a connection to the address of a `Listener` Returns a connection to the address of a `Listener`
''' '''
family = family or address_type(address) family = family or address_type(address)
_validate_family(family)
if family == 'AF_PIPE': if family == 'AF_PIPE':
c = PipeClient(address) c = PipeClient(address)
else: else:
......
...@@ -1829,7 +1829,7 @@ has the same effect as typing a particular string at the help> prompt. ...@@ -1829,7 +1829,7 @@ has the same effect as typing a particular string at the help> prompt.
Welcome to Python %s! This is the online help utility. Welcome to Python %s! This is the online help utility.
If this is your first time using Python, you should definitely check out If this is your first time using Python, you should definitely check out
the tutorial on the Internet at http://docs.python.org/tutorial/. the tutorial on the Internet at http://docs.python.org/%s/tutorial/.
Enter the name of any module, keyword, or topic to get help on writing Enter the name of any module, keyword, or topic to get help on writing
Python programs and using Python modules. To quit this help utility and Python programs and using Python modules. To quit this help utility and
...@@ -1839,7 +1839,7 @@ To get a list of available modules, keywords, or topics, type "modules", ...@@ -1839,7 +1839,7 @@ To get a list of available modules, keywords, or topics, type "modules",
"keywords", or "topics". Each module also comes with a one-line summary "keywords", or "topics". Each module also comes with a one-line summary
of what it does; to list the modules whose summaries contain a given word of what it does; to list the modules whose summaries contain a given word
such as "spam", type "modules spam". such as "spam", type "modules spam".
''' % sys.version[:3]) ''' % tuple([sys.version[:3]]*2))
def list(self, items, columns=4, width=80): def list(self, items, columns=4, width=80):
items = list(sorted(items)) items = list(sorted(items))
......
"""Word completion for GNU readline 2.0. """Word completion for GNU readline.
This requires the latest extension to the readline module. The completer The completer completes keywords, built-ins and globals in a selectable
completes keywords, built-ins and globals in a selectable namespace (which namespace (which defaults to __main__); when completing NAME.NAME..., it
defaults to __main__); when completing NAME.NAME..., it evaluates (!) the evaluates (!) the expression up to the last dot and completes its attributes.
expression up to the last dot and completes its attributes.
It's very cool to do "import sys" type "sys.", hit the It's very cool to do "import sys" type "sys.", hit the completion key (twice),
completion key (twice), and see the list of names defined by the and see the list of names defined by the sys module!
sys module!
Tip: to use the tab key as the completion key, call Tip: to use the tab key as the completion key, call
...@@ -15,21 +13,19 @@ Tip: to use the tab key as the completion key, call ...@@ -15,21 +13,19 @@ Tip: to use the tab key as the completion key, call
Notes: Notes:
- Exceptions raised by the completer function are *ignored* (and - Exceptions raised by the completer function are *ignored* (and generally cause
generally cause the completion to fail). This is a feature -- since the completion to fail). This is a feature -- since readline sets the tty
readline sets the tty device in raw (or cbreak) mode, printing a device in raw (or cbreak) mode, printing a traceback wouldn't work well
traceback wouldn't work well without some complicated hoopla to save, without some complicated hoopla to save, reset and restore the tty state.
reset and restore the tty state.
- The evaluation of the NAME.NAME... form may cause arbitrary - The evaluation of the NAME.NAME... form may cause arbitrary application
application defined code to be executed if an object with a defined code to be executed if an object with a __getattr__ hook is found.
__getattr__ hook is found. Since it is the responsibility of the Since it is the responsibility of the application (or the user) to enable this
application (or the user) to enable this feature, I consider this an feature, I consider this an acceptable risk. More complicated expressions
acceptable risk. More complicated expressions (e.g. function calls or (e.g. function calls or indexing operations) are *not* evaluated.
indexing operations) are *not* evaluated.
- When the original stdin is not a tty device, GNU readline is never - When the original stdin is not a tty device, GNU readline is never
used, and this module (and the readline module) are silently inactive. used, and this module (and the readline module) are silently inactive.
""" """
......
...@@ -197,6 +197,17 @@ class socket(_socket.socket): ...@@ -197,6 +197,17 @@ class socket(_socket.socket):
if self._io_refs <= 0: if self._io_refs <= 0:
self._real_close() self._real_close()
def detach(self):
"""detach() -> file descriptor
Close the socket object without closing the underlying file descriptor.
The object cannot be used after this call, but the file descriptor
can be reused for other purposes. The file descriptor is returned.
"""
self._closed = True
return super().detach()
def fromfd(fd, family, type, proto=0): def fromfd(fd, family, type, proto=0):
""" fromfd(fd, family, type[, proto]) -> socket object """ fromfd(fd, family, type[, proto]) -> socket object
......
...@@ -183,7 +183,9 @@ class ProcessPoolShutdownTest(ProcessPoolMixin, ExecutorShutdownTest): ...@@ -183,7 +183,9 @@ class ProcessPoolShutdownTest(ProcessPoolMixin, ExecutorShutdownTest):
for p in processes: for p in processes:
p.join() p.join()
class WaitTests(unittest.TestCase): class WaitTests(unittest.TestCase):
def test_first_completed(self): def test_first_completed(self):
future1 = self.executor.submit(mul, 21, 2) future1 = self.executor.submit(mul, 21, 2)
future2 = self.executor.submit(time.sleep, 1.5) future2 = self.executor.submit(time.sleep, 1.5)
...@@ -284,7 +286,21 @@ class WaitTests(unittest.TestCase): ...@@ -284,7 +286,21 @@ class WaitTests(unittest.TestCase):
class ThreadPoolWaitTests(ThreadPoolMixin, WaitTests): class ThreadPoolWaitTests(ThreadPoolMixin, WaitTests):
pass
def test_pending_calls_race(self):
# Issue #14406: multi-threaded race condition when waiting on all
# futures.
event = threading.Event()
def future_func():
event.wait()
oldswitchinterval = sys.getswitchinterval()
sys.setswitchinterval(1e-6)
try:
fs = {self.executor.submit(future_func) for i in range(100)}
event.set()
futures.wait(fs, return_when=futures.ALL_COMPLETED)
finally:
sys.setswitchinterval(oldswitchinterval)
class ProcessPoolWaitTests(ProcessPoolMixin, WaitTests): class ProcessPoolWaitTests(ProcessPoolMixin, WaitTests):
......
...@@ -2319,8 +2319,20 @@ class TestStdinBadfiledescriptor(unittest.TestCase): ...@@ -2319,8 +2319,20 @@ class TestStdinBadfiledescriptor(unittest.TestCase):
flike.flush() flike.flush()
assert sio.getvalue() == 'foo' assert sio.getvalue() == 'foo'
#
# Issue 14151: Test invalid family on invalid environment
#
class TestInvalidFamily(unittest.TestCase):
@unittest.skipIf(WIN32, "skipped on Windows")
def test_invalid_family(self):
with self.assertRaises(ValueError):
multiprocessing.connection.Listener(r'\\.\test')
testcases_other = [OtherTest, TestInvalidHandle, TestInitializers, testcases_other = [OtherTest, TestInvalidHandle, TestInitializers,
TestStdinBadfiledescriptor] TestStdinBadfiledescriptor, TestInvalidFamily]
# #
# #
......
...@@ -951,6 +951,7 @@ class BasicTCPTest(SocketConnectedTest): ...@@ -951,6 +951,7 @@ class BasicTCPTest(SocketConnectedTest):
f = self.cli_conn.detach() f = self.cli_conn.detach()
self.assertEqual(f, fileno) self.assertEqual(f, fileno)
# cli_conn cannot be used anymore... # cli_conn cannot be used anymore...
self.assertTrue(self.cli_conn._closed)
self.assertRaises(socket.error, self.cli_conn.recv, 1024) self.assertRaises(socket.error, self.cli_conn.recv, 1024)
self.cli_conn.close() self.cli_conn.close()
# ...but we can create another socket using the (still open) # ...but we can create another socket using the (still open)
......
...@@ -10,6 +10,9 @@ What's New in Python 3.2.4 ...@@ -10,6 +10,9 @@ What's New in Python 3.2.4
Core and Builtins Core and Builtins
----------------- -----------------
- Issue #13019: Fix potential reference leaks in bytearray.extend(). Patch
by Suman Saha.
- Issue #14378: Fix compiling ast.ImportFrom nodes with a "__future__" string as - Issue #14378: Fix compiling ast.ImportFrom nodes with a "__future__" string as
the module name that was not interned. the module name that was not interned.
...@@ -31,6 +34,21 @@ Core and Builtins ...@@ -31,6 +34,21 @@ Core and Builtins
Library Library
------- -------
- Issue #14151: Raise a ValueError, not a NameError, when trying to create
a multiprocessing Client or Listener with an AF_PIPE type address under
non-Windows platforms. Patch by Popa Claudiu.
- Issue #13872: socket.detach() now marks the socket closed (as mirrored
in the socket repr()). Patch by Matt Joiner.
- Issue #14406: Fix a race condition when using ``concurrent.futures.wait(
return_when=ALL_COMPLETED)``. Patch by Matt Joiner.
- Issue #14409: IDLE now properly executes commands in the Shell window
when it cannot read the normal config files on startup and
has to use the built-in default key bindings.
There was previously a bug in one of the defaults.
- Issue #10340: asyncore - properly handle EINVAL in dispatcher constructor on - Issue #10340: asyncore - properly handle EINVAL in dispatcher constructor on
OSX; avoid to call handle_connect in case of a disconnected socket which OSX; avoid to call handle_connect in case of a disconnected socket which
was not meant to connect. was not meant to connect.
...@@ -97,6 +115,8 @@ Extension Modules ...@@ -97,6 +115,8 @@ Extension Modules
Build Build
----- -----
- Issue #14437: Fix building the _io module under Cygwin.
- Issue #14387: Do not include accu.h from Python.h. - Issue #14387: Do not include accu.h from Python.h.
- Issue #14359: Only use O_CLOEXEC in _posixmodule.c if it is defined. - Issue #14359: Only use O_CLOEXEC in _posixmodule.c if it is defined.
......
...@@ -67,7 +67,7 @@ typedef struct { ...@@ -67,7 +67,7 @@ typedef struct {
PyObject *filename; /* Not used, but part of the IOError object */ PyObject *filename; /* Not used, but part of the IOError object */
Py_ssize_t written; Py_ssize_t written;
} PyBlockingIOErrorObject; } PyBlockingIOErrorObject;
PyAPI_DATA(PyObject *) PyExc_BlockingIOError; extern PyObject *PyExc_BlockingIOError;
/* /*
* Offset type for positioning. * Offset type for positioning.
......
...@@ -22,9 +22,9 @@ extern wchar_t* _Py_DecodeUTF8_surrogateescape(const char *s, Py_ssize_t size); ...@@ -22,9 +22,9 @@ extern wchar_t* _Py_DecodeUTF8_surrogateescape(const char *s, Py_ssize_t size);
int int
main(int argc, char **argv) main(int argc, char **argv)
{ {
wchar_t **argv_copy = (wchar_t **)PyMem_Malloc(sizeof(wchar_t*)*argc); wchar_t **argv_copy = (wchar_t **)PyMem_Malloc(sizeof(wchar_t*)*(argc+1));
/* We need a second copies, as Python might modify the first one. */ /* We need a second copies, as Python might modify the first one. */
wchar_t **argv_copy2 = (wchar_t **)PyMem_Malloc(sizeof(wchar_t*)*argc); wchar_t **argv_copy2 = (wchar_t **)PyMem_Malloc(sizeof(wchar_t*)*(argc+1));
int i, res; int i, res;
char *oldloc; char *oldloc;
/* 754 requires that FP exceptions run in "no stop" mode by default, /* 754 requires that FP exceptions run in "no stop" mode by default,
...@@ -58,6 +58,8 @@ main(int argc, char **argv) ...@@ -58,6 +58,8 @@ main(int argc, char **argv)
} }
argv_copy2[i] = argv_copy[i]; argv_copy2[i] = argv_copy[i];
} }
argv_copy2[argc] = argv_copy[argc] = NULL;
setlocale(LC_ALL, oldloc); setlocale(LC_ALL, oldloc);
free(oldloc); free(oldloc);
res = Py_Main(argc, argv_copy); res = Py_Main(argc, argv_copy);
......
...@@ -2234,8 +2234,10 @@ bytearray_extend(PyByteArrayObject *self, PyObject *arg) ...@@ -2234,8 +2234,10 @@ bytearray_extend(PyByteArrayObject *self, PyObject *arg)
} }
bytearray_obj = PyByteArray_FromStringAndSize(NULL, buf_size); bytearray_obj = PyByteArray_FromStringAndSize(NULL, buf_size);
if (bytearray_obj == NULL) if (bytearray_obj == NULL) {
Py_DECREF(it);
return NULL; return NULL;
}
buf = PyByteArray_AS_STRING(bytearray_obj); buf = PyByteArray_AS_STRING(bytearray_obj);
while ((item = PyIter_Next(it)) != NULL) { while ((item = PyIter_Next(it)) != NULL) {
...@@ -2268,8 +2270,10 @@ bytearray_extend(PyByteArrayObject *self, PyObject *arg) ...@@ -2268,8 +2270,10 @@ bytearray_extend(PyByteArrayObject *self, PyObject *arg)
return NULL; return NULL;
} }
if (bytearray_setslice(self, Py_SIZE(self), Py_SIZE(self), bytearray_obj) == -1) if (bytearray_setslice(self, Py_SIZE(self), Py_SIZE(self), bytearray_obj) == -1) {
Py_DECREF(bytearray_obj);
return NULL; return NULL;
}
Py_DECREF(bytearray_obj); Py_DECREF(bytearray_obj);
Py_RETURN_NONE; Py_RETURN_NONE;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment