 +static int lp_status(lua_State *L) {
 +  PStream *p = (PStream *)luaL_checkudata(L, 1, "ta_spawn");
 +  lua_pushstring(L, p->pid ? "running" : "terminated");
-+  return 1;
+   return 1;
+ }
+ 
++/** Process exit cleanup function. */
++static void exited(PStream *p, int status) {
++#if _WIN32
++  close(p->pid);
++#endif
++  close(p->fstdin), close(p->fstdout), close(p->fstderr);
++  luaL_unref(p->L, LUA_REGISTRYINDEX, p->stdout_cb);
++  luaL_unref(p->L, LUA_REGISTRYINDEX, p->stderr_cb);
++  luaL_unref(p->L, LUA_REGISTRYINDEX, p->exit_cb);
++  luaL_unref(p->L, LUA_REGISTRYINDEX, p->ref); // allow proc to be collected
++  p->pid = 0, p->exit_status = status;
 +}
 +
 +/** p:wait() Lua function. */
 +static int lp_wait(lua_State *L) {
 +  PStream *p = (PStream *)luaL_checkudata(L, 1, "ta_spawn");
-+  luaL_argcheck(L, p->pid, 1, "process terminated");
++  if (!p->pid) return (lua_pushinteger(L, p->exit_status), 1);
 +#if !_WIN32
 +  int status;
 +  waitpid(p->pid, &status, 0);

+  lua_State *L;
+  int ref;
+#if !_WIN32
+  int pid, fstdin, fstdout, fstderr;
+#else
+  HANDLE pid, fstdin, fstdout, fstderr;
+#endif

+    lua_pushfstring(L, "process (pid=%d)", p->pid);
+  else
+    lua_pushstring(L, "process (terminated)");
+  return 1;
+}
+
+#if (GTK && !__APPLE__)
+/** __gc Lua metamethod. */
+static int lp_gc(lua_State *L) {
