| 
									
										
										
										
											2008-06-13 19:28:21 +00:00
										 |  |  | /*
 | 
					
						
							|  |  |  |  * A type which wraps a pipe handle in message oriented mode | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * pipe_connection.c | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Copyright (c) 2006-2008, R Oudkerk --- see COPYING.txt | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include "multiprocessing.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #define CLOSE(h) CloseHandle(h)
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*
 | 
					
						
							|  |  |  |  * Send string to the pipe; assumes in message oriented mode | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static Py_ssize_t | 
					
						
							|  |  |  | conn_send_string(ConnectionObject *conn, char *string, size_t length) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |     DWORD amount_written; | 
					
						
							|  |  |  |     BOOL ret; | 
					
						
							| 
									
										
										
										
											2008-06-13 19:28:21 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |     Py_BEGIN_ALLOW_THREADS | 
					
						
							|  |  |  |     ret = WriteFile(conn->handle, string, length, &amount_written, NULL); | 
					
						
							|  |  |  |     Py_END_ALLOW_THREADS | 
					
						
							| 
									
										
										
											
												Merged revisions 70908,70939,71009,71022,71036 via svnmerge from
svn+ssh://pythondev@svn.python.org/python/trunk
........
  r70908 | jesse.noller | 2009-03-31 17:20:35 -0500 (Tue, 31 Mar 2009) | 1 line
  Issue 5619: Pass MS CRT debug flags into subprocesses
........
  r70939 | jesse.noller | 2009-03-31 22:45:50 -0500 (Tue, 31 Mar 2009) | 1 line
  Fix multiprocessing.event to match the new threading.Event API
........
  r71009 | jesse.noller | 2009-04-01 19:03:28 -0500 (Wed, 01 Apr 2009) | 1 line
  issue5545: Switch to Autoconf for multiprocessing; special thanks to Martin Lowis for help
........
  r71022 | jesse.noller | 2009-04-01 21:32:55 -0500 (Wed, 01 Apr 2009) | 1 line
  Issue 3110: Additional protection for SEM_VALUE_MAX on platforms, thanks to Martin Loewis
........
  r71036 | jesse.noller | 2009-04-01 23:22:09 -0500 (Wed, 01 Apr 2009) | 1 line
  Issue 3551: Raise ValueError if the size causes ERROR_NO_SYSTEM_RESOURCES
........
											
										 
											2009-04-05 21:24:58 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |     if (ret == 0 && GetLastError() == ERROR_NO_SYSTEM_RESOURCES) { | 
					
						
							|  |  |  |         PyErr_Format(PyExc_ValueError, "Cannnot send %" PY_FORMAT_SIZE_T "d bytes over connection", length); | 
					
						
							|  |  |  |         return MP_STANDARD_ERROR; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
											
												Merged revisions 70908,70939,71009,71022,71036 via svnmerge from
svn+ssh://pythondev@svn.python.org/python/trunk
........
  r70908 | jesse.noller | 2009-03-31 17:20:35 -0500 (Tue, 31 Mar 2009) | 1 line
  Issue 5619: Pass MS CRT debug flags into subprocesses
........
  r70939 | jesse.noller | 2009-03-31 22:45:50 -0500 (Tue, 31 Mar 2009) | 1 line
  Fix multiprocessing.event to match the new threading.Event API
........
  r71009 | jesse.noller | 2009-04-01 19:03:28 -0500 (Wed, 01 Apr 2009) | 1 line
  issue5545: Switch to Autoconf for multiprocessing; special thanks to Martin Lowis for help
........
  r71022 | jesse.noller | 2009-04-01 21:32:55 -0500 (Wed, 01 Apr 2009) | 1 line
  Issue 3110: Additional protection for SEM_VALUE_MAX on platforms, thanks to Martin Loewis
........
  r71036 | jesse.noller | 2009-04-01 23:22:09 -0500 (Wed, 01 Apr 2009) | 1 line
  Issue 3551: Raise ValueError if the size causes ERROR_NO_SYSTEM_RESOURCES
........
											
										 
											2009-04-05 21:24:58 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |     return ret ? MP_SUCCESS : MP_STANDARD_ERROR; | 
					
						
							| 
									
										
										
										
											2008-06-13 19:28:21 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*
 | 
					
						
							|  |  |  |  * Attempts to read into buffer, or if buffer too small into *newbuffer. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Returns number of bytes read.  Assumes in message oriented mode. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static Py_ssize_t | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  | conn_recv_string(ConnectionObject *conn, char *buffer, | 
					
						
							|  |  |  |                  size_t buflength, char **newbuffer, size_t maxlength) | 
					
						
							| 
									
										
										
										
											2008-06-13 19:28:21 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |     DWORD left, length, full_length, err; | 
					
						
							|  |  |  |     BOOL ret; | 
					
						
							|  |  |  |     *newbuffer = NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     Py_BEGIN_ALLOW_THREADS | 
					
						
							|  |  |  |     ret = ReadFile(conn->handle, buffer, MIN(buflength, maxlength), | 
					
						
							|  |  |  |                   &length, NULL); | 
					
						
							|  |  |  |     Py_END_ALLOW_THREADS | 
					
						
							|  |  |  |     if (ret) | 
					
						
							|  |  |  |         return length; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     err = GetLastError(); | 
					
						
							|  |  |  |     if (err != ERROR_MORE_DATA) { | 
					
						
							|  |  |  |         if (err == ERROR_BROKEN_PIPE) | 
					
						
							|  |  |  |             return MP_END_OF_FILE; | 
					
						
							|  |  |  |         return MP_STANDARD_ERROR; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (!PeekNamedPipe(conn->handle, NULL, 0, NULL, NULL, &left)) | 
					
						
							|  |  |  |         return MP_STANDARD_ERROR; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     full_length = length + left; | 
					
						
							|  |  |  |     if (full_length > maxlength) | 
					
						
							|  |  |  |         return MP_BAD_MESSAGE_LENGTH; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     *newbuffer = PyMem_Malloc(full_length); | 
					
						
							|  |  |  |     if (*newbuffer == NULL) | 
					
						
							|  |  |  |         return MP_MEMORY_ERROR; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     memcpy(*newbuffer, buffer, length); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     Py_BEGIN_ALLOW_THREADS | 
					
						
							|  |  |  |     ret = ReadFile(conn->handle, *newbuffer+length, left, &length, NULL); | 
					
						
							|  |  |  |     Py_END_ALLOW_THREADS | 
					
						
							|  |  |  |     if (ret) { | 
					
						
							|  |  |  |         assert(length == left); | 
					
						
							|  |  |  |         return full_length; | 
					
						
							|  |  |  |     } else { | 
					
						
							|  |  |  |         PyMem_Free(*newbuffer); | 
					
						
							|  |  |  |         return MP_STANDARD_ERROR; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2008-06-13 19:28:21 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*
 | 
					
						
							|  |  |  |  * Check whether any data is available for reading | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int | 
					
						
							| 
									
										
										
										
											2009-01-20 00:23:01 +00:00
										 |  |  | conn_poll(ConnectionObject *conn, double timeout, PyThreadState *_save) | 
					
						
							| 
									
										
										
										
											2008-06-13 19:28:21 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |     DWORD bytes, deadline, delay; | 
					
						
							|  |  |  |     int difference, res; | 
					
						
							|  |  |  |     BOOL block = FALSE; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (!PeekNamedPipe(conn->handle, NULL, 0, NULL, &bytes, NULL)) | 
					
						
							|  |  |  |         return MP_STANDARD_ERROR; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (timeout == 0.0) | 
					
						
							|  |  |  |         return bytes > 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (timeout < 0.0) | 
					
						
							|  |  |  |         block = TRUE; | 
					
						
							|  |  |  |     else | 
					
						
							|  |  |  |         /* XXX does not check for overflow */ | 
					
						
							|  |  |  |         deadline = GetTickCount() + (DWORD)(1000 * timeout + 0.5); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     Sleep(0); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     for (delay = 1 ; ; delay += 1) { | 
					
						
							|  |  |  |         if (!PeekNamedPipe(conn->handle, NULL, 0, NULL, &bytes, NULL)) | 
					
						
							|  |  |  |             return MP_STANDARD_ERROR; | 
					
						
							|  |  |  |         else if (bytes > 0) | 
					
						
							|  |  |  |             return TRUE; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (!block) { | 
					
						
							|  |  |  |             difference = deadline - GetTickCount(); | 
					
						
							|  |  |  |             if (difference < 0) | 
					
						
							|  |  |  |                 return FALSE; | 
					
						
							|  |  |  |             if ((int)delay > difference) | 
					
						
							|  |  |  |                 delay = difference; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (delay > 20) | 
					
						
							|  |  |  |             delay = 20; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         Sleep(delay); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         /* check for signals */ | 
					
						
							|  |  |  |         Py_BLOCK_THREADS | 
					
						
							|  |  |  |         res = PyErr_CheckSignals(); | 
					
						
							|  |  |  |         Py_UNBLOCK_THREADS | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (res) | 
					
						
							|  |  |  |             return MP_EXCEPTION_HAS_BEEN_SET; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2008-06-13 19:28:21 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*
 | 
					
						
							|  |  |  |  * "connection.h" defines the PipeConnection type using the definitions above | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #define CONNECTION_NAME "PipeConnection"
 | 
					
						
							|  |  |  | #define CONNECTION_TYPE PipeConnectionType
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include "connection.h"
 |