summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--PRESUBMIT.py1
-rw-r--r--native_client_sdk/src/examples/tutorial/using_ppapi_simple/example.js13
-rw-r--r--native_client_sdk/src/examples/tutorial/using_ppapi_simple/index.html2
-rw-r--r--native_client_sdk/src/libraries/nacl_io/kernel_intercept.cc20
-rw-r--r--native_client_sdk/src/libraries/nacl_io/kernel_intercept.h13
-rw-r--r--native_client_sdk/src/libraries/nacl_io/kernel_proxy.cc15
-rw-r--r--native_client_sdk/src/libraries/nacl_io/kernel_proxy.h8
-rw-r--r--native_client_sdk/src/libraries/nacl_io/kernel_wrap_glibc.cc18
-rw-r--r--native_client_sdk/src/libraries/nacl_io/kernel_wrap_newlib.cc11
-rw-r--r--native_client_sdk/src/libraries/nacl_io/kernel_wrap_real.h1
-rw-r--r--native_client_sdk/src/libraries/nacl_io/nacl_io.cc11
-rw-r--r--native_client_sdk/src/libraries/nacl_io/nacl_io.h5
-rw-r--r--native_client_sdk/src/libraries/ppapi_simple/ps_instance.cc97
-rw-r--r--native_client_sdk/src/libraries/ppapi_simple/ps_instance.h28
-rw-r--r--native_client_sdk/src/tests/nacl_io_socket_test/example.js3
-rw-r--r--native_client_sdk/src/tests/nacl_io_test/example.dsc1
-rw-r--r--native_client_sdk/src/tests/nacl_io_test/example.js3
-rw-r--r--native_client_sdk/src/tests/nacl_io_test/fuse_fs_test.cc4
-rw-r--r--native_client_sdk/src/tests/nacl_io_test/mock_kernel_proxy.h3
-rw-r--r--native_client_sdk/src/tests/sdk_util_test/example.js2
20 files changed, 202 insertions, 57 deletions
diff --git a/PRESUBMIT.py b/PRESUBMIT.py
index ced5de4..3e18813 100644
--- a/PRESUBMIT.py
+++ b/PRESUBMIT.py
@@ -906,6 +906,7 @@ def _CheckSpamLogging(input_api, output_api):
r"logging_native_handler\.cc$",
r"^content[\\\/]common[\\\/]gpu[\\\/]client[\\\/]"
r"gl_helper_benchmark\.cc$",
+ r"^native_client_sdk[\\\/]",
r"^remoting[\\\/]base[\\\/]logging\.h$",
r"^remoting[\\\/]host[\\\/].*",
r"^sandbox[\\\/]linux[\\\/].*",
diff --git a/native_client_sdk/src/examples/tutorial/using_ppapi_simple/example.js b/native_client_sdk/src/examples/tutorial/using_ppapi_simple/example.js
index 7f26921..03b9a4e 100644
--- a/native_client_sdk/src/examples/tutorial/using_ppapi_simple/example.js
+++ b/native_client_sdk/src/examples/tutorial/using_ppapi_simple/example.js
@@ -8,6 +8,17 @@ function moduleDidLoad() {
}
// Called by the common.js module.
+// nacl_io/ppapi_simple generates two different types of messages:
+// - messages from /dev/tty (prefixed with PS_TTY_PREFIX)
+// - exit message (prefixed with PS_EXIT_MESSAGE)
function handleMessage(message) {
- common.logMessage(message.data);
+ if (message.data.indexOf("exit:") == 0) {
+ // When we recieve the exit message we post an empty reply back to
+ // confirm, at which point the module will exit.
+ message.srcElement.postMessage({"exit" : ""});
+ } else if (message.data.indexOf("tty:") == 0) {
+ common.logMessage(message.data.slice("tty:".length));
+ } else {
+ console.log("Unhandled message: " + message.data);
+ }
}
diff --git a/native_client_sdk/src/examples/tutorial/using_ppapi_simple/index.html b/native_client_sdk/src/examples/tutorial/using_ppapi_simple/index.html
index 8779f49..fabbf9a 100644
--- a/native_client_sdk/src/examples/tutorial/using_ppapi_simple/index.html
+++ b/native_client_sdk/src/examples/tutorial/using_ppapi_simple/index.html
@@ -12,7 +12,7 @@ found in the LICENSE file.
<script type="text/javascript" src="common.js"></script>
<script type="text/javascript" src="example.js"></script>
</head>
-<body {{attrs}} data-attrs="ps_stdout=dev/tty">
+<body {{attrs}} data-attrs="PS_STDOUT=dev/tty PS_TTY_PREFIX=tty: PS_EXIT_MESSAGE=exit">
<h1>{{title}}</h1>
<h2>Status: <code id="statusField">NO-STATUS</code></h2>
<p>The Hello World Stdio example is the simplest one in the SDK. It uses the
diff --git a/native_client_sdk/src/libraries/nacl_io/kernel_intercept.cc b/native_client_sdk/src/libraries/nacl_io/kernel_intercept.cc
index aca1ef3..ce4f170 100644
--- a/native_client_sdk/src/libraries/nacl_io/kernel_intercept.cc
+++ b/native_client_sdk/src/libraries/nacl_io/kernel_intercept.cc
@@ -10,6 +10,7 @@
#include "nacl_io/kernel_proxy.h"
#include "nacl_io/kernel_wrap.h"
+#include "nacl_io/kernel_wrap_real.h"
#include "nacl_io/osmman.h"
#include "nacl_io/ossocket.h"
#include "nacl_io/pepper_interface.h"
@@ -81,14 +82,6 @@ int ki_init_interface(void* kp, void* pepper_interface) {
return 0;
}
-int ki_register_fs_type(const char* fs_type, struct fuse_operations* fuse_ops) {
- return s_state.kp->RegisterFsType(fs_type, fuse_ops);
-}
-
-int ki_unregister_fs_type(const char* fs_type) {
- return s_state.kp->UnregisterFsType(fs_type);
-}
-
int ki_is_initialized() {
return s_state.kp != NULL;
}
@@ -112,11 +105,22 @@ void ki_uninit() {
delete delete_kp;
}
+nacl_io::KernelProxy* ki_get_proxy() {
+ return s_state.kp;
+}
+
int ki_chdir(const char* path) {
ON_NOSYS_RETURN(-1);
return s_state.kp->chdir(path);
}
+void ki_exit(int status) {
+ if (ki_is_initialized())
+ s_state.kp->exit(status);
+
+ _real_exit(status);
+}
+
char* ki_getcwd(char* buf, size_t size) {
// gtest uses getcwd in a static initializer. If we haven't initialized the
// kernel-intercept yet, just return ".".
diff --git a/native_client_sdk/src/libraries/nacl_io/kernel_intercept.h b/native_client_sdk/src/libraries/nacl_io/kernel_intercept.h
index bcf86b2..9b72f58 100644
--- a/native_client_sdk/src/libraries/nacl_io/kernel_intercept.h
+++ b/native_client_sdk/src/libraries/nacl_io/kernel_intercept.h
@@ -21,6 +21,12 @@
EXTERN_C_BEGIN
+#ifdef __cplusplus
+namespace nacl_io {
+class KernelProxy;
+}
+#endif
+
struct fuse_operations;
/*
@@ -54,12 +60,15 @@ int ki_init_ppapi(void* kernel_proxy,
*/
int ki_init_interface(void* kernel_proxy, void* pepper_interface);
-int ki_register_fs_type(const char* fs_type, struct fuse_operations* fuse_ops);
-int ki_unregister_fs_type(const char* fs_type);
+#ifdef __cplusplus
+nacl_io::KernelProxy* ki_get_proxy();
+#endif
+
int ki_is_initialized();
void ki_uninit();
int ki_chdir(const char* path);
+void ki_exit(int status);
char* ki_getcwd(char* buf, size_t size);
char* ki_getwd(char* buf);
int ki_dup(int oldfd);
diff --git a/native_client_sdk/src/libraries/nacl_io/kernel_proxy.cc b/native_client_sdk/src/libraries/nacl_io/kernel_proxy.cc
index 9c59b6a..6d750be 100644
--- a/native_client_sdk/src/libraries/nacl_io/kernel_proxy.cc
+++ b/native_client_sdk/src/libraries/nacl_io/kernel_proxy.cc
@@ -51,6 +51,7 @@ namespace nacl_io {
KernelProxy::KernelProxy() : dev_(0), ppapi_(NULL),
+ exit_handler_(NULL),
signal_emitter_(new EventEmitter) {
memset(&sigwinch_handler_, 0, sizeof(sigwinch_handler_));
sigwinch_handler_.sa_handler = SIG_DFL;
@@ -144,6 +145,15 @@ bool KernelProxy::UnregisterFsType(const char* fs_type) {
return true;
}
+bool KernelProxy::RegisterExitHandler(nacl_io_exit_handler_t exit_handler,
+ void* user_data) {
+ if (exit_handler_ != NULL)
+ return false;
+ exit_handler_ = exit_handler;
+ exit_handler_user_data_ = user_data;
+ return true;
+}
+
int KernelProxy::open_resource(const char* path) {
ScopedFilesystem fs;
Path rel;
@@ -268,6 +278,11 @@ int KernelProxy::chdir(const char* path) {
return 0;
}
+void KernelProxy::exit(int status) {
+ if (exit_handler_)
+ exit_handler_(status, exit_handler_user_data_);
+}
+
char* KernelProxy::getcwd(char* buf, size_t size) {
if (NULL == buf) {
errno = EFAULT;
diff --git a/native_client_sdk/src/libraries/nacl_io/kernel_proxy.h b/native_client_sdk/src/libraries/nacl_io/kernel_proxy.h
index 7344d31..1cb1cc2 100644
--- a/native_client_sdk/src/libraries/nacl_io/kernel_proxy.h
+++ b/native_client_sdk/src/libraries/nacl_io/kernel_proxy.h
@@ -12,6 +12,7 @@
#include "nacl_io/fs_factory.h"
#include "nacl_io/host_resolver.h"
#include "nacl_io/kernel_object.h"
+#include "nacl_io/nacl_io.h"
#include "nacl_io/ossignal.h"
#include "nacl_io/ossocket.h"
#include "nacl_io/ostypes.h"
@@ -55,6 +56,9 @@ class KernelProxy : protected KernelObject {
bool RegisterFsType(const char* fs_type, fuse_operations* fuse_ops);
bool UnregisterFsType(const char* fs_type);
+ bool RegisterExitHandler(nacl_io_exit_handler_t exit_handler,
+ void* user_data);
+
virtual int pipe(int pipefds[2]);
// NaCl-only function to read resources specified in the NMF file.
@@ -66,6 +70,8 @@ class KernelProxy : protected KernelObject {
virtual int dup(int fd);
virtual int dup2(int fd, int newfd);
+ virtual void exit(int status);
+
// Path related System calls handled by KernelProxy (not filesystem-specific)
virtual int chdir(const char* path);
virtual char* getcwd(char* buf, size_t size);
@@ -207,6 +213,8 @@ class KernelProxy : protected KernelObject {
PepperInterface* ppapi_;
static KernelProxy *s_instance_;
struct sigaction sigwinch_handler_;
+ nacl_io_exit_handler_t exit_handler_;
+ void* exit_handler_user_data_;
#ifdef PROVIDES_SOCKET_API
HostResolver host_resolver_;
#endif
diff --git a/native_client_sdk/src/libraries/nacl_io/kernel_wrap_glibc.cc b/native_client_sdk/src/libraries/nacl_io/kernel_wrap_glibc.cc
index d6e44bd..f895ffb 100644
--- a/native_client_sdk/src/libraries/nacl_io/kernel_wrap_glibc.cc
+++ b/native_client_sdk/src/libraries/nacl_io/kernel_wrap_glibc.cc
@@ -127,10 +127,11 @@ EXTERN_C_BEGIN
OP(chdir); \
OP(close); \
OP(dup); \
- OP(dup2); \
+ OP(dup2); \
+ OP(exit); \
OP(fstat); \
- OP(getcwd); \
- OP(getdents); \
+ OP(getcwd); \
+ OP(getdents); \
OP(mkdir); \
OP(open); \
OP(poll);\
@@ -146,7 +147,7 @@ EXTERN_C_BEGIN
EXPAND_SYMBOL_LIST_OPERATION(DECLARE_REAL_PTR);
-int WRAP(chdir) (const char* pathname) {
+int WRAP(chdir)(const char* pathname) {
return (ki_chdir(pathname)) ? errno : 0;
}
@@ -163,6 +164,10 @@ int WRAP(dup2)(int fd, int newfd) NOTHROW {
return (ki_dup2(fd, newfd) < 0) ? errno : 0;
}
+void WRAP(exit)(int status) {
+ ki_exit(status);
+}
+
int WRAP(fstat)(int fd, struct nacl_abi_stat *nacl_buf) {
struct stat buf;
memset(&buf, 0, sizeof(struct stat));
@@ -301,6 +306,11 @@ int _real_close(int fd) {
return REAL(close)(fd);
}
+void _real_exit(int status) {
+ CHECK_REAL(exit);
+ REAL(exit)(status);
+}
+
int _real_fstat(int fd, struct stat* buf) {
struct nacl_abi_stat st;
CHECK_REAL(fstat);
diff --git a/native_client_sdk/src/libraries/nacl_io/kernel_wrap_newlib.cc b/native_client_sdk/src/libraries/nacl_io/kernel_wrap_newlib.cc
index 0809866..6cf5184 100644
--- a/native_client_sdk/src/libraries/nacl_io/kernel_wrap_newlib.cc
+++ b/native_client_sdk/src/libraries/nacl_io/kernel_wrap_newlib.cc
@@ -47,6 +47,7 @@ EXTERN_C_BEGIN
extern void __libnacl_irt_dev_filename_init(void);
+extern struct nacl_irt_basic __libnacl_irt_basic;
extern struct nacl_irt_fdio __libnacl_irt_fdio;
extern struct nacl_irt_dev_fdio __libnacl_irt_dev_fdio;
extern struct nacl_irt_dev_filename __libnacl_irt_dev_filename;
@@ -54,6 +55,7 @@ extern struct nacl_irt_memory __libnacl_irt_memory;
// Create function pointers to the REAL implementation
#define EXPAND_SYMBOL_LIST_OPERATION(OP) \
+ OP(basic, exit); \
OP(fdio, close); \
OP(fdio, dup); \
OP(fdio, dup2); \
@@ -103,6 +105,10 @@ int WRAP(dup2)(int fd, int newfd) {
return (newfd < 0) ? errno : 0;
}
+void WRAP(exit)(int status) {
+ ki_exit(status);
+}
+
int WRAP(read)(int fd, void* buf, size_t count, size_t* nread) {
ssize_t signed_nread = ki_read(fd, buf, count);
*nread = static_cast<size_t>(signed_nread);
@@ -261,6 +267,11 @@ int _real_close(int fd) {
return REAL(close)(fd);
}
+void _real_exit(int status) {
+ CHECK_REAL(exit);
+ REAL(exit)(status);
+}
+
int _real_fstat(int fd, struct stat* buf) {
CHECK_REAL(fstat);
return REAL(fstat)(fd, buf);
diff --git a/native_client_sdk/src/libraries/nacl_io/kernel_wrap_real.h b/native_client_sdk/src/libraries/nacl_io/kernel_wrap_real.h
index 9a9bce6..68840ac 100644
--- a/native_client_sdk/src/libraries/nacl_io/kernel_wrap_real.h
+++ b/native_client_sdk/src/libraries/nacl_io/kernel_wrap_real.h
@@ -12,6 +12,7 @@
EXTERN_C_BEGIN
int _real_close(int fd);
+void _real_exit(int status);
int _real_fstat(int fd, struct stat *buf);
int _real_getdents(int fd, void* nacl_buf, size_t nacl_count, size_t *nread);
int _real_lseek(int fd, off_t offset, int whence, off_t* new_offset);
diff --git a/native_client_sdk/src/libraries/nacl_io/nacl_io.cc b/native_client_sdk/src/libraries/nacl_io/nacl_io.cc
index b4e21d3..ee61e9d 100644
--- a/native_client_sdk/src/libraries/nacl_io/nacl_io.cc
+++ b/native_client_sdk/src/libraries/nacl_io/nacl_io.cc
@@ -6,6 +6,7 @@
#include <stdlib.h>
#include "nacl_io/kernel_intercept.h"
+#include "nacl_io/kernel_proxy.h"
void nacl_io_init() {
ki_init(NULL);
@@ -16,10 +17,16 @@ void nacl_io_init_ppapi(PP_Instance instance,
ki_init_ppapi(NULL, instance, get_interface);
}
+
int nacl_io_register_fs_type(const char* fs_type, fuse_operations* fuse_ops) {
- return ki_register_fs_type(fs_type, fuse_ops);
+ return ki_get_proxy()->RegisterFsType(fs_type, fuse_ops);
}
int nacl_io_unregister_fs_type(const char* fs_type) {
- return ki_unregister_fs_type(fs_type);
+ return ki_get_proxy()->UnregisterFsType(fs_type);
+}
+
+int nacl_io_register_exit_handler(nacl_io_exit_handler_t exit_handler,
+ void* user_data) {
+ return ki_get_proxy()->RegisterExitHandler(exit_handler, user_data);
}
diff --git a/native_client_sdk/src/libraries/nacl_io/nacl_io.h b/native_client_sdk/src/libraries/nacl_io/nacl_io.h
index 7c49222..5250903 100644
--- a/native_client_sdk/src/libraries/nacl_io/nacl_io.h
+++ b/native_client_sdk/src/libraries/nacl_io/nacl_io.h
@@ -12,6 +12,8 @@
EXTERN_C_BEGIN
+typedef void (*nacl_io_exit_handler_t)(int status, void* user_data);
+
/**
* Initialize nacl_io.
*
@@ -40,6 +42,9 @@ void nacl_io_init();
*/
void nacl_io_init_ppapi(PP_Instance instance, PPB_GetInterface get_interface);
+int nacl_io_register_exit_handler(nacl_io_exit_handler_t exit_handler,
+ void* user_data);
+
/**
* Mount a new filesystem type.
*
diff --git a/native_client_sdk/src/libraries/ppapi_simple/ps_instance.cc b/native_client_sdk/src/libraries/ppapi_simple/ps_instance.cc
index a4b0d41..a9c7168 100644
--- a/native_client_sdk/src/libraries/ppapi_simple/ps_instance.cc
+++ b/native_client_sdk/src/libraries/ppapi_simple/ps_instance.cc
@@ -60,21 +60,11 @@ struct StartInfo {
void* PSInstance::MainThreadThunk(void *info) {
s_InstanceObject->Trace("Got MainThreadThunk.\n");
StartInfo* si = static_cast<StartInfo*>(info);
- si->inst_->main_loop_ = new pp::MessageLoop(si->inst_);
- si->inst_->main_loop_->AttachToCurrentThread();
+ PSInstance* instance = si->inst_;
+ instance->main_loop_ = new pp::MessageLoop(si->inst_);
+ instance->main_loop_->AttachToCurrentThread();
- int ret = si->inst_->MainThread(si->argc_, si->argv_);
-
- bool should_exit = si->inst_->exit_message_ == NULL;
-
- if (si->inst_->exit_message_) {
- // Send the exit message to JavaScript. Don't call exit(), so the message
- // doesn't get dropped.
- si->inst_->Log("Posting exit message to JavaScript.\n");
- std::stringstream ss;
- ss << si->inst_->exit_message_ << ":" << ret;
- si->inst_->PostMessage(ss.str());
- }
+ int ret = instance->MainThread(si->argc_, si->argv_);
// Clean up StartInfo.
for (uint32_t i = 0; i < si->argc_; i++) {
@@ -83,16 +73,34 @@ void* PSInstance::MainThreadThunk(void *info) {
delete[] si->argv_;
delete si;
- if (should_exit) {
- // Exit the entire process once the 'main' thread returns.
- // The error code will be available to javascript via
- // the exitcode parameter of the crash event.
- exit(ret);
- }
-
+ // Exit the entire process once the 'main' thread returns.
+ // The error code will be available to javascript via
+ // the exitcode parameter of the crash event.
+#ifdef __native_client__
+ exit(ret);
+#else
+ instance->ExitHandshake(ret);
+#endif
return NULL;
}
+void PSInstance::ExitHandshake(int status) {
+ if (exit_message_ == NULL)
+ return;
+
+ RegisterMessageHandler(exit_message_, MessageHandlerExitStatic, this);
+
+ // Send the exit message to JavaScript. Then wait
+ // for the reply/confirmation.
+ std::stringstream ss;
+ ss << exit_message_ << ":" << status;
+
+ pthread_mutex_lock(&exit_lock_);
+ PostMessage(ss.str());
+ pthread_cond_wait(&exit_cond_, &exit_lock_);
+ pthread_mutex_unlock(&exit_lock_);
+}
+
// The default implementation supports running a 'C' main.
int PSInstance::MainThread(int argc, char* argv[]) {
if (!main_cb_) {
@@ -117,6 +125,10 @@ PSInstance::PSInstance(PP_Instance instance)
tty_fd_(-1),
tty_prefix_(NULL),
exit_message_(NULL) {
+
+ pthread_mutex_init(&exit_lock_, NULL);
+ pthread_cond_init(&exit_cond_, NULL);
+
// Set the single Instance object
s_InstanceObject = this;
@@ -130,7 +142,9 @@ PSInstance::PSInstance(PP_Instance instance)
PP_INPUTEVENT_CLASS_TOUCH);
}
-PSInstance::~PSInstance() {}
+PSInstance::~PSInstance() {
+ s_InstanceObject = NULL;
+}
void PSInstance::SetMain(PSMainFunc_t main) {
main_cb_ = main;
@@ -207,17 +221,18 @@ bool PSInstance::Init(uint32_t arg,
// initialization macro, or via dynamically set embed attributes
// through instance DidCreate.
bool PSInstance::ProcessProperties() {
- // Set default values
- setenv("PS_STDIN", "/dev/stdin", 0);
- setenv("PS_STDOUT", "/dev/stdout", 0);
- setenv("PS_STDERR", "/dev/console3", 0);
-
// Reset verbosity if passed in
const char* verbosity = getenv("PS_VERBOSITY");
if (verbosity) SetVerbosity(static_cast<Verbosity>(atoi(verbosity)));
// Enable NaCl IO to map STDIN, STDOUT, and STDERR
nacl_io_init_ppapi(PSGetInstanceId(), PSGetInterface);
+
+ // Set default values
+ setenv("PS_STDIN", "/dev/stdin", 0);
+ setenv("PS_STDOUT", "/dev/stdout", 0);
+ setenv("PS_STDERR", "/dev/console3", 0);
+
int fd0 = open(getenv("PS_STDIN"), O_RDONLY);
dup2(fd0, 0);
@@ -267,6 +282,11 @@ bool PSInstance::ProcessProperties() {
exit_message_ = getenv("PS_EXIT_MESSAGE");
+ // If PS_EXIT_MESSAGE is set in the envionment then we perform a handshake
+ // with JavaScript when program exits.
+ if (exit_message_ != NULL)
+ nacl_io_register_exit_handler(HandleExitStatic, this);
+
// Set line buffering on stdout and stderr
#if !defined(WIN32)
setvbuf(stderr, NULL, _IOLBF, 0);
@@ -370,6 +390,13 @@ ssize_t PSInstance::TtyOutputHandler(const char* buf, size_t count) {
return count;
}
+void PSInstance::MessageHandlerExit(const pp::Var& message) {
+ assert(message.is_string());
+ pthread_mutex_lock(&exit_lock_);
+ pthread_cond_signal(&exit_cond_);
+ pthread_mutex_unlock(&exit_lock_);
+}
+
void PSInstance::MessageHandlerInput(const pp::Var& message) {
// Since our message may contain null characters, we can't send it as a
// naked C string, so we package it up in this struct before sending it
@@ -387,7 +414,12 @@ void PSInstance::MessageHandlerInput(const pp::Var& message) {
}
}
-void PSInstance::HandleResize(int width, int height){
+void PSInstance::HandleExitStatic(int status, void* user_data) {
+ PSInstance* instance = reinterpret_cast<PSInstance*>(user_data);
+ instance->ExitHandshake(status);
+}
+
+void PSInstance::HandleResize(int width, int height) {
struct winsize size;
memset(&size, 0, sizeof(size));
size.ws_col = width;
@@ -412,6 +444,13 @@ ssize_t PSInstance::TtyOutputHandlerStatic(const char* buf,
return instance->TtyOutputHandler(buf, count);
}
+void PSInstance::MessageHandlerExitStatic(const pp::Var& key,
+ const pp::Var& value,
+ void* user_data) {
+ PSInstance* instance = reinterpret_cast<PSInstance*>(user_data);
+ instance->MessageHandlerExit(value);
+}
+
void PSInstance::MessageHandlerInputStatic(const pp::Var& key,
const pp::Var& value,
void* user_data) {
@@ -459,7 +498,7 @@ void PSInstance::PostEvent(PSEventType type, const PP_Var& var) {
// If the message is a dictionary then see if it matches one
// of the specific handlers, then call that handler rather than
// queuing an event.
- if (tty_fd_ >= 0 && event.is_dictionary()) {
+ if (event.is_dictionary()) {
pp::VarDictionary dictionary(var);
pp::VarArray keys = dictionary.GetKeys();
if (keys.GetLength() == 1) {
diff --git a/native_client_sdk/src/libraries/ppapi_simple/ps_instance.h b/native_client_sdk/src/libraries/ppapi_simple/ps_instance.h
index 4138982..48908b0 100644
--- a/native_client_sdk/src/libraries/ppapi_simple/ps_instance.h
+++ b/native_client_sdk/src/libraries/ppapi_simple/ps_instance.h
@@ -109,6 +109,12 @@ class PSInstance : public pp::Instance, pp::MouseLock, pp::Graphics3DClient {
MessageHandler_t handler,
void* user_data);
+
+ // Perform exit handshake with JavaScript.
+ // This is called by _exit before the process is terminated to ensure
+ // that all messages sent prior to _exit arrive at the JavaScript side.
+ void ExitHandshake(int status);
+
protected:
typedef std::map<std::string, MessageHandler> MessageHandlerMap;
@@ -148,17 +154,24 @@ class PSInstance : public pp::Instance, pp::MouseLock, pp::Graphics3DClient {
// Called by Init to processes default and embed tag arguments prior to
// launching the 'ppapi_main' thread.
virtual bool ProcessProperties();
-
private:
static void* MainThreadThunk(void *start_info);
ssize_t TtyOutputHandler(const char* buf, size_t count);
+ void MessageHandlerExit(const pp::Var& message);
void MessageHandlerInput(const pp::Var& message);
void MessageHandlerResize(const pp::Var& message);
void HandleResize(int width, int height);
+ static void HandleExitStatic(int status, void* user_data);
+
static ssize_t TtyOutputHandlerStatic(const char* buf, size_t count,
void* user_data);
+ /// Handle exit confirmation message from JavaScript.
+ static void MessageHandlerExitStatic(const pp::Var& key,
+ const pp::Var& value,
+ void* user_data);
+
/// Handle input message from JavaScript. The value is
/// expected to be of type string.
static void MessageHandlerInputStatic(const pp::Var& key,
@@ -185,15 +198,20 @@ class PSInstance : public pp::Instance, pp::MouseLock, pp::Graphics3DClient {
const char* tty_prefix_;
MessageHandlerMap message_handlers_;
- // A message to Post to JavaScript instead of exiting, or NULL if exit()
- // should be called instead.
- char* exit_message_;
-
PSMainFunc_t main_cb_;
const PPB_Core* ppb_core_;
const PPB_Var* ppb_var_;
const PPB_View* ppb_view_;
+
+ // Condition variable and lock used to wait for exit confirmation from
+ // JavaScript.
+ pthread_cond_t exit_cond_;
+ pthread_mutex_t exit_lock_;
+
+ // A message to Post to JavaScript instead of exiting, or NULL if exit()
+ // should be called instead.
+ char* exit_message_;
};
#endif // PPAPI_MAIN_PS_INSTANCE_H_
diff --git a/native_client_sdk/src/tests/nacl_io_socket_test/example.js b/native_client_sdk/src/tests/nacl_io_socket_test/example.js
index 24b8243..2ffb98d 100644
--- a/native_client_sdk/src/tests/nacl_io_socket_test/example.js
+++ b/native_client_sdk/src/tests/nacl_io_socket_test/example.js
@@ -63,6 +63,9 @@ function handleMessage(event) {
var cmdFunctionName = cmd + 'Command';
var cmdFunction = window[cmdFunctionName];
+ if (cmd == 'testend')
+ event.srcElement.postMessage({'testend' : ''});
+
if (typeof(cmdFunction) !== 'function') {
console.log('Unknown command: ' + cmd);
console.log(' message: ' + msg);
diff --git a/native_client_sdk/src/tests/nacl_io_test/example.dsc b/native_client_sdk/src/tests/nacl_io_test/example.dsc
index 7b2db96..48f7a54 100644
--- a/native_client_sdk/src/tests/nacl_io_test/example.dsc
+++ b/native_client_sdk/src/tests/nacl_io_test/example.dsc
@@ -47,7 +47,6 @@
'mem_fs_node_test.cc',
'mock_fs.cc',
'mock_fs.h',
- 'mock_kernel_proxy.cc',
'mock_kernel_proxy.h',
'mock_node.cc',
'mock_node.h',
diff --git a/native_client_sdk/src/tests/nacl_io_test/example.js b/native_client_sdk/src/tests/nacl_io_test/example.js
index 24b8243..2146595 100644
--- a/native_client_sdk/src/tests/nacl_io_test/example.js
+++ b/native_client_sdk/src/tests/nacl_io_test/example.js
@@ -60,6 +60,9 @@ function handleMessage(event) {
var msg = event.data;
var firstColon = msg.indexOf(':');
var cmd = firstColon !== -1 ? msg.substr(0, firstColon) : msg;
+ if (cmd == 'testend')
+ event.srcElement.postMessage({'testend' : ''});
+
var cmdFunctionName = cmd + 'Command';
var cmdFunction = window[cmdFunctionName];
diff --git a/native_client_sdk/src/tests/nacl_io_test/fuse_fs_test.cc b/native_client_sdk/src/tests/nacl_io_test/fuse_fs_test.cc
index bacf6a8..a75246d 100644
--- a/native_client_sdk/src/tests/nacl_io_test/fuse_fs_test.cc
+++ b/native_client_sdk/src/tests/nacl_io_test/fuse_fs_test.cc
@@ -321,7 +321,7 @@ void KernelProxyFuseTest::SetUp() {
ASSERT_EQ(0, ki_init(&kp_));
// Register a fuse filesystem.
- ki_register_fs_type("flatfs", &g_fuse_operations);
+ nacl_io_register_fs_type("flatfs", &g_fuse_operations);
// Unmount the passthrough FS and mount our fuse filesystem.
EXPECT_EQ(0, kp_.umount("/"));
@@ -329,7 +329,7 @@ void KernelProxyFuseTest::SetUp() {
}
void KernelProxyFuseTest::TearDown() {
- ki_unregister_fs_type("flatfs");
+ nacl_io_unregister_fs_type("flatfs");
ki_uninit();
}
diff --git a/native_client_sdk/src/tests/nacl_io_test/mock_kernel_proxy.h b/native_client_sdk/src/tests/nacl_io_test/mock_kernel_proxy.h
index 12d06b6..2402b76 100644
--- a/native_client_sdk/src/tests/nacl_io_test/mock_kernel_proxy.h
+++ b/native_client_sdk/src/tests/nacl_io_test/mock_kernel_proxy.h
@@ -16,8 +16,7 @@
class MockKernelProxy : public nacl_io::KernelProxy {
public:
- MockKernelProxy();
- virtual ~MockKernelProxy();
+ MockKernelProxy() {}
MOCK_METHOD2(access, int(const char*, int));
MOCK_METHOD1(chdir, int(const char*));
diff --git a/native_client_sdk/src/tests/sdk_util_test/example.js b/native_client_sdk/src/tests/sdk_util_test/example.js
index 24b8243..8538ccd 100644
--- a/native_client_sdk/src/tests/sdk_util_test/example.js
+++ b/native_client_sdk/src/tests/sdk_util_test/example.js
@@ -62,6 +62,8 @@ function handleMessage(event) {
var cmd = firstColon !== -1 ? msg.substr(0, firstColon) : msg;
var cmdFunctionName = cmd + 'Command';
var cmdFunction = window[cmdFunctionName];
+ if (cmd == 'testend')
+ event.srcElement.postMessage({'testend' : ''});
if (typeof(cmdFunction) !== 'function') {
console.log('Unknown command: ' + cmd);