From 704d7686f3eeb4af928ae3ff8d2ab11ac600f7cb Mon Sep 17 00:00:00 2001 From: David Rose Date: Fri, 12 Jun 2009 16:14:20 +0000 Subject: [PATCH] more osx --- direct/src/plugin/p3dPythonRun.cxx | 10 +- direct/src/plugin/p3dPythonRun.h | 2 +- direct/src/plugin/p3dSession.cxx | 303 ++++++++++++++++++++++------- direct/src/plugin/p3dSession.h | 16 ++ direct/src/plugin/panda3d.cxx | 51 +++-- 5 files changed, 286 insertions(+), 96 deletions(-) diff --git a/direct/src/plugin/p3dPythonRun.cxx b/direct/src/plugin/p3dPythonRun.cxx index 1ba3a0e143..c56dc52cc0 100755 --- a/direct/src/plugin/p3dPythonRun.cxx +++ b/direct/src/plugin/p3dPythonRun.cxx @@ -52,7 +52,11 @@ P3DPythonRun(int argc, char *argv[]) { _pipe_read.open_read(read); _pipe_write.open_write(write); +#else + _pipe_read.open_read(STDIN_FILENO); + _pipe_write.open_write(STDOUT_FILENO); #endif // _WIN32 + if (!_pipe_read) { cerr << "unable to open read pipe\n"; } @@ -233,7 +237,7 @@ spawn_read_thread() { _read_thread_continue = true; #ifdef _WIN32 - _read_thread = CreateThread(NULL, 0, &win_rt_thread_run, this, 0, NULL); + _read_thread = CreateThread(NULL, 0, &rt_thread_run, this, 0, NULL); #else pthread_attr_t attr; pthread_attr_init(&attr); @@ -406,7 +410,7 @@ rt_thread_run() { #ifdef _WIN32 //////////////////////////////////////////////////////////////////// -// Function: P3DPython::win_rt_thread_run +// Function: P3DPythonRun::win_rt_thread_run // Access: Private, Static // Description: The Windows flavor of the thread callback function. //////////////////////////////////////////////////////////////////// @@ -419,7 +423,7 @@ win_rt_thread_run(LPVOID data) { #ifndef _WIN32 //////////////////////////////////////////////////////////////////// -// Function: P3DPython::win_rt_thread_run +// Function: P3DPythonRun::posix_rt_thread_run // Access: Private, Static // Description: The Posix flavor of the thread callback function. //////////////////////////////////////////////////////////////////// diff --git a/direct/src/plugin/p3dPythonRun.h b/direct/src/plugin/p3dPythonRun.h index b39f67ca3f..b1ab92501d 100755 --- a/direct/src/plugin/p3dPythonRun.h +++ b/direct/src/plugin/p3dPythonRun.h @@ -114,7 +114,7 @@ private: #ifdef _WIN32 HANDLE _read_thread; #else - pthread_t _thread; + pthread_t _read_thread; #endif }; diff --git a/direct/src/plugin/p3dSession.cxx b/direct/src/plugin/p3dSession.cxx index 3b77b639e5..6b571b9ef9 100644 --- a/direct/src/plugin/p3dSession.cxx +++ b/direct/src/plugin/p3dSession.cxx @@ -16,6 +16,10 @@ #include "p3dInstance.h" #include "p3dInstanceManager.h" +#ifndef _WIN32 +#include +#endif + //////////////////////////////////////////////////////////////////// // Function: P3DSession::Constructor // Access: Public @@ -29,7 +33,12 @@ P3DSession:: P3DSession(P3DInstance *inst) { _session_key = inst->get_session_key(); _python_version = inst->get_python_version(); + +#ifdef _WIN32 _python_root_dir = "C:/p3drun"; +#else + _python_root_dir = "/Users/drose/p3drun"; +#endif _python_state = PS_init; _started_read_thread = false; @@ -188,6 +197,7 @@ send_command(TiXmlDocument *command) { //////////////////////////////////////////////////////////////////// void P3DSession:: download_p3dpython(P3DInstance *inst) { + /* P3DFileDownload *download = new P3DFileDownload(); download->set_url("http://fewmet/~drose/p3drun.tgz"); @@ -198,8 +208,9 @@ download_p3dpython(P3DInstance *inst) { } inst->start_download(download); + */ - // start_p3dpython(); + start_p3dpython(); } //////////////////////////////////////////////////////////////////// @@ -209,8 +220,12 @@ download_p3dpython(P3DInstance *inst) { //////////////////////////////////////////////////////////////////// void P3DSession:: start_p3dpython() { +#ifdef _WIN32 string p3dpython = "c:/cygwin/home/drose/player/direct/built/bin/p3dpython.exe"; // string p3dpython = _python_root_dir + "/p3dpython.exe"; +#else + string p3dpython = "/Users/drose/player/direct/built/bin/p3dpython"; +#endif // Populate the new process' environment. string env; @@ -243,78 +258,9 @@ start_p3dpython() { env += _python_root_dir; env += '\0'; - // Create a bi-directional pipe to communicate with the sub-process. -#ifdef _WIN32 - HANDLE r_to, w_to, r_from, w_from; - - // Create the pipe to the process. - if (!CreatePipe(&r_to, &w_to, NULL, 0)) { - cerr << "failed to create pipe\n"; - } else { - // Make sure the right end of the pipe is inheritable. - SetHandleInformation(r_to, HANDLE_FLAG_INHERIT, HANDLE_FLAG_INHERIT); - SetHandleInformation(w_to, HANDLE_FLAG_INHERIT, 0); - } - - // Create the pipe from the process. - if (!CreatePipe(&r_from, &w_from, NULL, 0)) { - cerr << "failed to create pipe\n"; - } else { - // Make sure the right end of the pipe is inheritable. - SetHandleInformation(w_from, HANDLE_FLAG_INHERIT, HANDLE_FLAG_INHERIT); - SetHandleInformation(r_from, HANDLE_FLAG_INHERIT, 0); - } - - HANDLE error_handle = GetStdHandle(STD_ERROR_HANDLE); - bool got_output_filename = !_output_filename.empty(); - if (got_output_filename) { - // Open the named file for output and redirect the child's stderr - // into it. - HANDLE handle = CreateFile - (_output_filename.c_str(), GENERIC_WRITE, - FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, - NULL, CREATE_ALWAYS, 0, NULL); - if (handle != INVALID_HANDLE_VALUE) { - error_handle = handle; - SetHandleInformation(error_handle, HANDLE_FLAG_INHERIT, HANDLE_FLAG_INHERIT); - } else { - cerr << "Unable to open " << _output_filename << "\n"; - } - } - - // Make sure we see an error dialog if there is a missing DLL. - SetErrorMode(0); - - // Pass the appropriate ends of the bi-directional pipe as the - // standard input and standard output of the child process. - STARTUPINFO startup_info; - ZeroMemory(&startup_info, sizeof(STARTUPINFO)); - startup_info.cb = sizeof(startup_info); - startup_info.hStdError = error_handle; - startup_info.hStdOutput = w_from; - startup_info.hStdInput = r_to; - startup_info.dwFlags |= STARTF_USESTDHANDLES; - - // Make sure the "python" console window is hidden. - startup_info.wShowWindow = SW_HIDE; - startup_info.dwFlags |= STARTF_USESHOWWINDOW; - - BOOL result = CreateProcess - (p3dpython.c_str(), NULL, NULL, NULL, TRUE, 0, - (void *)env.c_str(), _python_root_dir.c_str(), - &startup_info, &_p3dpython); - bool started_p3dpython = (result != 0); - - // Close the pipe handles that are now owned by the child. - CloseHandle(w_from); - CloseHandle(r_to); - if (got_output_filename) { - CloseHandle(error_handle); - } - - _pipe_read.open_read(r_from); - _pipe_write.open_write(w_to); -#endif // _WIN32 + bool started_p3dpython = create_process + (p3dpython, _python_root_dir, env, _output_filename, + _pipe_read, _pipe_write); if (!started_p3dpython) { cerr << "Failed to create process.\n"; @@ -322,7 +268,7 @@ start_p3dpython() { } _python_state = PS_running; - cerr << "Created process: " << _p3dpython.dwProcessId << "\n"; + cerr << "Created child process\n"; if (!_pipe_read) { cerr << "unable to open read pipe\n"; @@ -364,6 +310,12 @@ spawn_read_thread() { _read_thread_continue = true; #ifdef _WIN32 _read_thread = CreateThread(NULL, 0, &win_rt_thread_run, this, 0, NULL); +#else + pthread_attr_t attr; + pthread_attr_init(&attr); + pthread_attr_setscope(&attr, PTHREAD_SCOPE_SYSTEM); + pthread_create(&_read_thread, &attr, &posix_rt_thread_run, (void *)this); + pthread_attr_destroy(&attr); #endif _started_read_thread = true; } @@ -388,6 +340,9 @@ join_read_thread() { WaitForSingleObject(_read_thread, INFINITE); CloseHandle(_read_thread); _read_thread = NULL; +#else + void *return_val; + pthread_join(_read_thread, &return_val); #endif cerr << "session done waiting for thread\n"; @@ -448,7 +403,7 @@ rt_terminate() { #ifdef _WIN32 //////////////////////////////////////////////////////////////////// -// Function: P3DPython::win_rt_thread_run +// Function: P3DSession::win_rt_thread_run // Access: Private, Static // Description: The Windows flavor of the thread callback function. //////////////////////////////////////////////////////////////////// @@ -458,3 +413,201 @@ win_rt_thread_run(LPVOID data) { return 0; } #endif + +#ifndef _WIN32 +//////////////////////////////////////////////////////////////////// +// Function: P3DSession::posix_rt_thread_run +// Access: Private, Static +// Description: The Posix flavor of the thread callback function. +//////////////////////////////////////////////////////////////////// +void *P3DSession:: +posix_rt_thread_run(void *data) { + ((P3DSession *)data)->rt_thread_run(); + return NULL; +} +#endif + + +#ifdef _WIN32 +//////////////////////////////////////////////////////////////////// +// Function: P3DSession::create_process +// Access: Private, Static +// Description: Creates a sub-process to run the named program +// executable, with the indicated environment string. +// Standard error is logged to output_filename, if that +// string is nonempty. +// +// Opens the two HandleStreams as the read and write +// pipes to the child process's standard output and +// standard input, respectively. Returns true on +// success, false on failure. +//////////////////////////////////////////////////////////////////// +bool P3DSession:: +create_process(const string &program, const string &start_dir, + const string &env, const string &output_filename, + HandleStream &pipe_read, HandleStream &pipe_write) { + // This is the Windows variant. + + // Create a bi-directional pipe to communicate with the sub-process. + HANDLE r_to, w_to, r_from, w_from; + + // Create the pipe to the process. + if (!CreatePipe(&r_to, &w_to, NULL, 0)) { + cerr << "failed to create pipe\n"; + } else { + // Make sure the right end of the pipe is inheritable. + SetHandleInformation(r_to, HANDLE_FLAG_INHERIT, HANDLE_FLAG_INHERIT); + SetHandleInformation(w_to, HANDLE_FLAG_INHERIT, 0); + } + + // Create the pipe from the process. + if (!CreatePipe(&r_from, &w_from, NULL, 0)) { + cerr << "failed to create pipe\n"; + } else { + // Make sure the right end of the pipe is inheritable. + SetHandleInformation(w_from, HANDLE_FLAG_INHERIT, HANDLE_FLAG_INHERIT); + SetHandleInformation(r_from, HANDLE_FLAG_INHERIT, 0); + } + + HANDLE error_handle = GetStdHandle(STD_ERROR_HANDLE); + bool got_output_filename = !output_filename.empty(); + if (got_output_filename) { + // Open the named file for output and redirect the child's stderr + // into it. + HANDLE handle = CreateFile + (output_filename.c_str(), GENERIC_WRITE, + FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, + NULL, CREATE_ALWAYS, 0, NULL); + if (handle != INVALID_HANDLE_VALUE) { + error_handle = handle; + SetHandleInformation(error_handle, HANDLE_FLAG_INHERIT, HANDLE_FLAG_INHERIT); + } else { + cerr << "Unable to open " << output_filename << "\n"; + } + } + + // Make sure we see an error dialog if there is a missing DLL. + SetErrorMode(0); + + // Pass the appropriate ends of the bi-directional pipe as the + // standard input and standard output of the child process. + STARTUPINFO startup_info; + ZeroMemory(&startup_info, sizeof(STARTUPINFO)); + startup_info.cb = sizeof(startup_info); + startup_info.hStdError = error_handle; + startup_info.hStdOutput = w_from; + startup_info.hStdInput = r_to; + startup_info.dwFlags |= STARTF_USESTDHANDLES; + + // Make sure the "python" console window is hidden. + startup_info.wShowWindow = SW_HIDE; + startup_info.dwFlags |= STARTF_USESHOWWINDOW; + + BOOL result = CreateProcess + (program.c_str(), NULL, NULL, NULL, TRUE, 0, + (void *)env.c_str(), start_dir.c_str(), + &startup_info, &_program); + bool started_program = (result != 0); + + // Close the pipe handles that are now owned by the child. + CloseHandle(w_from); + CloseHandle(r_to); + if (got_output_filename) { + CloseHandle(error_handle); + } + + pipe_read.open_read(r_from); + pipe_write.open_write(w_to); + + return started_program; +} +#endif // _WIN32 + + +#ifndef _WIN32 +//////////////////////////////////////////////////////////////////// +// Function: P3DSession::create_process +// Access: Private, Static +// Description: Creates a sub-process to run the named program +// executable, with the indicated environment string. +// +// Opens the two HandleStreams as the read and write +// pipes to the child process's standard output and +// standard input, respectively. Returns true on +// success, false on failure. +//////////////////////////////////////////////////////////////////// +bool P3DSession:: +create_process(const string &program, const string &start_dir, + const string &env, const string &output_filename, + HandleStream &pipe_read, HandleStream &pipe_write) { + // This is the Posix variant. + + // Create a bi-directional pipe to communicate with the sub-process. + int to_fd[2]; + if (pipe(to_fd) < 0) { + perror("failed to create pipe"); + } + int from_fd[2]; + if (pipe(from_fd) < 0) { + perror("failed to create pipe"); + } + + // Fork and exec. + pid_t child = fork(); + if (child < 0) { + perror("fork"); + return false; + } + + if (child == 0) { + // Here we are in the child process. + bool got_output_filename = !output_filename.empty(); + if (got_output_filename) { + // Open the named file for output and redirect the child's stderr + // into it. + int logfile_fd = open(output_filename.c_str(), + O_WRONLY | O_CREAT | O_TRUNC, 0666); + if (logfile_fd < 0) { + cerr << "Unable to open " << output_filename << "\n"; + } else { + dup2(logfile_fd, STDERR_FILENO); + close(logfile_fd); + } + } + + // Set the appropriate ends of the bi-directional pipe as the + // standard input and standard output of the child process. + dup2(to_fd[0], STDIN_FILENO); + dup2(from_fd[1], STDOUT_FILENO); + close(to_fd[1]); + close(from_fd[0]); + + if (chdir(start_dir.c_str()) < 0) { + cerr << "Could not chdir to " << start_dir << "\n"; + _exit(1); + } + + // build up an array of char strings for the environment. + vector ptrs; + size_t p = 0; + size_t zero = env.find('\0', p); + while (zero != string::npos) { + ptrs.push_back(env.data() + p); + p = zero + 1; + zero = env.find('\0', p); + } + ptrs.push_back((char *)NULL); + + execle(program.c_str(), program.c_str(), (char *)0, &ptrs[0]); + cerr << "Failed to exec " << program << "\n"; + _exit(1); + } + + pipe_read.open_read(from_fd[0]); + pipe_write.open_write(to_fd[1]); + close(to_fd[0]); + close(from_fd[1]); + + return true; +} +#endif // _WIN32 diff --git a/direct/src/plugin/p3dSession.h b/direct/src/plugin/p3dSession.h index b1a36e378f..634710fd12 100644 --- a/direct/src/plugin/p3dSession.h +++ b/direct/src/plugin/p3dSession.h @@ -59,6 +59,20 @@ private: #ifdef _WIN32 static DWORD WINAPI win_rt_thread_run(LPVOID data); +#else + static void *posix_rt_thread_run(void *data); +#endif + +#ifdef _WIN32 + static bool + create_process(const string &program, const string &start_dir, + const string &env, const string &output_filename, + HandleStream &pipe_read, HandleStream &pipe_write); +#else + static bool + create_process(const string &program, const string &start_dir, + const string &env, const string &output_filename, + HandleStream &pipe_read, HandleStream &pipe_write); #endif private: @@ -99,6 +113,8 @@ private: bool _read_thread_continue; #ifdef _WIN32 HANDLE _read_thread; +#else + pthread_t _read_thread; #endif }; diff --git a/direct/src/plugin/panda3d.cxx b/direct/src/plugin/panda3d.cxx index 8b5e1d9d10..34db46e135 100644 --- a/direct/src/plugin/panda3d.cxx +++ b/direct/src/plugin/panda3d.cxx @@ -24,6 +24,8 @@ #ifdef _WIN32 #include +#else +#include #endif #include "httpClient.h" @@ -41,6 +43,14 @@ #endif #endif +#ifdef _WIN32 +static const string dll_ext = ".dll"; +#elif defined(__APPLE__) +static const string dll_ext = ".dylib"; +#else +static const string dll_ext = ".so"; +#endif + static const string default_plugin_filename = "libp3d_plugin"; P3D_initialize_func *P3D_initialize; @@ -148,12 +158,7 @@ load_plugin(const string &p3d_plugin_filename) { string filename = p3d_plugin_filename; if (filename.empty()) { // Look for the plugin along the path. - filename = default_plugin_filename; -#ifdef _WIN32 - filename += ".dll"; -#else - filename += ".so"; -#endif + filename = default_plugin_filename + dll_ext; } #ifdef _WIN32 @@ -163,16 +168,6 @@ load_plugin(const string &p3d_plugin_filename) { return false; } - // Get the full path to the DLL in case it was found along the path. - static const buffer_size = 4096; - static char buffer[buffer_size]; - if (GetModuleFileName(module, buffer, buffer_size) != 0) { - if (GetLastError() != 0) { - filename = buffer; - } - } - cerr << filename << "\n"; - // Now get all of the function pointers. P3D_initialize = (P3D_initialize_func *)GetProcAddress(module, "P3D_initialize"); P3D_free_string = (P3D_free_string_func *)GetProcAddress(module, "P3D_free_string"); @@ -185,6 +180,28 @@ load_plugin(const string &p3d_plugin_filename) { P3D_check_request = (P3D_check_request_func *)GetProcAddress(module, "P3D_check_request"); P3D_request_finish = (P3D_request_finish_func *)GetProcAddress(module, "P3D_request_finish"); P3D_instance_feed_url_stream = (P3D_instance_feed_url_stream_func *)GetProcAddress(module, "P3D_instance_feed_url_stream"); + +#else // _WIN32 + // Posix case. + void *module = dlopen(filename.c_str(), RTLD_NOW | RTLD_LOCAL); + if (module == NULL) { + // Couldn't load the .so. + return false; + } + + // Now get all of the function pointers. + P3D_initialize = (P3D_initialize_func *)dlsym(module, "P3D_initialize"); + P3D_free_string = (P3D_free_string_func *)dlsym(module, "P3D_free_string"); + P3D_create_instance = (P3D_create_instance_func *)dlsym(module, "P3D_create_instance"); + P3D_instance_finish = (P3D_instance_finish_func *)dlsym(module, "P3D_instance_finish"); + P3D_instance_has_property = (P3D_instance_has_property_func *)dlsym(module, "P3D_instance_has_property"); + P3D_instance_get_property = (P3D_instance_get_property_func *)dlsym(module, "P3D_instance_get_property"); + P3D_instance_set_property = (P3D_instance_set_property_func *)dlsym(module, "P3D_instance_set_property"); + P3D_instance_get_request = (P3D_instance_get_request_func *)dlsym(module, "P3D_instance_get_request"); + P3D_check_request = (P3D_check_request_func *)dlsym(module, "P3D_check_request"); + P3D_request_finish = (P3D_request_finish_func *)dlsym(module, "P3D_request_finish"); + P3D_instance_feed_url_stream = (P3D_instance_feed_url_stream_func *)dlsym(module, "P3D_instance_feed_url_stream"); + #endif // _WIN32 // Ensure that all of the function pointers have been found. @@ -329,7 +346,7 @@ usage() { << "Options:\n\n" - << " -p p3d_plugin.dll\n" + << " -p p3d_plugin" << dll_ext << "\n" << " Specify the full path to the particular Panda plugin DLL to\n" << " run. Normally, this will be found by searching in the usual\n" << " places.\n\n"