[thrift] Propogate exceptions from transports in thrift_protocol extension

Summary: Otherwise, it will spin forever if your socket connection gets dropped
  or otherwise times out.
Reviewed by: dbraginsky
Test plan: Modified TSocket to always throw an exception on read() and tried
  some service calls
Revert: svn


git-svn-id: https://svn.apache.org/repos/asf/incubator/thrift/trunk@665652 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/lib/php/src/ext/thrift_protocol/php_thrift_protocol.cpp b/lib/php/src/ext/thrift_protocol/php_thrift_protocol.cpp
index 86e8921..a2b80d8 100644
--- a/lib/php/src/ext/thrift_protocol/php_thrift_protocol.cpp
+++ b/lib/php/src/ext/thrift_protocol/php_thrift_protocol.cpp
@@ -75,6 +75,19 @@
 ZEND_GET_MODULE(thrift_protocol)
 #endif
 
+class PHPExceptionWrapper : public std::exception {
+public:
+  PHPExceptionWrapper(zval* _ex) throw() : ex(_ex) {
+    snprintf(_what, 40, "PHP exception zval=%p", ex);
+  }
+  const char* what() const throw() { return _what; }
+  ~PHPExceptionWrapper() throw() {}
+  operator zval*() const throw() { return const_cast<zval*>(ex); } // Zend API doesn't do 'const'...
+protected:
+  zval* ex;
+  char _what[40];
+} ;
+
 class PHPTransport {
 public:
   zval* protocol() { return p; }
@@ -198,6 +211,11 @@
     call_user_function(EG(function_table), &t, &writefn, &ret, 1, args TSRMLS_CC);
     zval_ptr_dtor(args);
     zval_dtor(&ret);
+    if (EG(exception)) {
+      zval* ex = EG(exception);
+      EG(exception) = NULL;
+      throw PHPExceptionWrapper(ex);
+    }
   }
 };
 
@@ -306,6 +324,13 @@
     call_user_function(EG(function_table), &t, &funcname, &retval, 1, args TSRMLS_CC);
     zval_ptr_dtor(args);
 
+    if (EG(exception)) {
+      zval_dtor(&retval);
+      zval* ex = EG(exception);
+      EG(exception) = NULL;
+      throw PHPExceptionWrapper(ex);
+    }
+
     buffer_used = Z_STRLEN(retval);
     memcpy(buffer, Z_STRVAL(retval), buffer_used);
     zval_dtor(&retval);
@@ -337,19 +362,6 @@
   zval_ptr_dtor(&ctor_rv);
 }
 
-class PHPExceptionWrapper : public std::exception {
-public:
-  PHPExceptionWrapper(zval* _ex) throw() : ex(_ex) {
-    snprintf(_what, 40, "PHP exception zval=%p", ex);
-  }
-  const char* what() const throw() { return _what; }
-  ~PHPExceptionWrapper() throw() {}
-  operator zval*() const throw() { return const_cast<zval*>(ex); } // Zend API doesn't do 'const'...
-protected:
-  zval* ex;
-  char _what[40];
-} ;
-
 void throw_tprotocolexception(char* what, long errorcode) {
   TSRMLS_FETCH();