Patch #1454481:  Make thread stack size runtime tunable.

Heavily revised, comprising revisions:
46640 - original trunk revision (backed out in r46655)
46647 - markup fix (backed out in r46655)
46692:46918 merged from branch aimacintyre-sf1454481

branch tested on buildbots (Windows buildbots had problems
not related to these changes).
diff --git a/Lib/test/output/test_thread b/Lib/test/output/test_thread
index d49651d..d8174ab 100644
--- a/Lib/test/output/test_thread
+++ b/Lib/test/output/test_thread
@@ -4,3 +4,15 @@
 
 *** Barrier Test ***
 all tasks done
+
+*** Changing thread stack size ***
+caught expected ValueError setting stack_size(4096)
+successfully set stack_size(32768)
+successfully set stack_size(1048576)
+successfully set stack_size(0)
+trying stack_size = 32768
+waiting for all tasks to complete
+all tasks done
+trying stack_size = 1048576
+waiting for all tasks to complete
+all tasks done
diff --git a/Lib/test/test_thread.py b/Lib/test/test_thread.py
index ea345b6..7b523e2 100644
--- a/Lib/test/test_thread.py
+++ b/Lib/test/test_thread.py
@@ -115,3 +115,46 @@
     thread.start_new_thread(task2, (i,))
 done.acquire()
 print 'all tasks done'
+
+# not all platforms support changing thread stack size
+print '\n*** Changing thread stack size ***'
+if thread.stack_size() != 0:
+    raise ValueError, "initial stack_size not 0"
+
+thread.stack_size(0) 
+if thread.stack_size() != 0:
+    raise ValueError, "stack_size not reset to default"
+
+from os import name as os_name
+if os_name in ("nt", "os2", "posix"):
+
+    tss_supported = 1
+    try:
+        thread.stack_size(4096)
+    except ValueError:
+        print 'caught expected ValueError setting stack_size(4096)'
+    except thread.ThreadError:
+        tss_supported = 0
+        print 'platform does not support changing thread stack size'
+
+    if tss_supported:
+        failed = lambda s, e: s != e
+        fail_msg = "stack_size(%d) failed - should succeed"
+        for tss in (32768, 0x100000, 0):
+            thread.stack_size(tss)
+            if failed(thread.stack_size(), tss):
+                raise ValueError, fail_msg % tss
+            print 'successfully set stack_size(%d)' % tss
+
+        for tss in (32768, 0x100000):
+            print 'trying stack_size = %d' % tss
+            next_ident = 0
+            for i in range(numtasks):
+                newtask()
+
+            print 'waiting for all tasks to complete'
+            done.acquire()
+            print 'all tasks done'
+
+        # reset stack size to default
+        thread.stack_size(0)
diff --git a/Lib/test/test_threading.py b/Lib/test/test_threading.py
index 7eb9758..02f338a 100644
--- a/Lib/test/test_threading.py
+++ b/Lib/test/test_threading.py
@@ -85,6 +85,22 @@
             print 'all tasks done'
         self.assertEqual(numrunning.get(), 0)
 
+    # run with a minimum thread stack size (32kB)
+    def test_various_ops_small_stack(self):
+        if verbose:
+            print 'with 32kB thread stack size...'
+        threading.stack_size(0x8000)
+        self.test_various_ops()
+        threading.stack_size(0)
+
+    # run with a large thread stack size (1MB)
+    def test_various_ops_large_stack(self):
+        if verbose:
+            print 'with 1MB thread stack size...'
+        threading.stack_size(0x100000)
+        self.test_various_ops()
+        threading.stack_size(0)
+
     def test_foreign_thread(self):
         # Check that a "foreign" thread can use the threading module.
         def f(mutex):