//virtual bool LLTextureCacheWorker::doWork(S32 param) { //allocate a new local apr_pool LLAPRPool pool ; //save the current mFileAPRPool to avoid breaking anything. apr_pool_t* old_pool = mCache->getFileAPRPool() ; //make mFileAPRPool to point to the local one mCache->setFileAPRPool(pool.getAPRPool()) ; bool res = false; if (param == 0) // read { res = doRead(); } else if (param == 1) // write { res = doWrite(); } else { llassert_always(0); } //set mFileAPRPool back, the local one will be released automatically. mCache->setFileAPRPool(old_pool) ; return res; }
// Added to mitigate the effect of libcurl looking // for the ALL_PROXY and http_proxy env variables // and deciding to insert a Pragma: no-cache // header! The only usage of this method at the // time of this writing is in llhttpclient.cpp // in the request() method, where this method // is called with use_proxy = FALSE void LLURLRequest::useProxy(bool use_proxy) { static char *env_proxy; if (use_proxy && (env_proxy == NULL)) { apr_status_t status; LLAPRPool pool; status = apr_env_get(&env_proxy, "ALL_PROXY", pool.getAPRPool()); if (status != APR_SUCCESS) { status = apr_env_get(&env_proxy, "http_proxy", pool.getAPRPool()); } if (status != APR_SUCCESS) { use_proxy = FALSE; } } lldebugs << "use_proxy = " << (use_proxy?'Y':'N') << ", env_proxy = " << (env_proxy ? env_proxy : "(null)") << llendl; if (env_proxy && use_proxy) { mDetail->mCurlRequest->setoptString(CURLOPT_PROXY, env_proxy); } else { mDetail->mCurlRequest->setoptString(CURLOPT_PROXY, ""); } }
static void initialize() { static bool initialized = false; if (!initialized) { apr_dso_handle_t* hprog = 0; LLAPRPool pool; pool.create(); #if LL_WINDOWS apr_dso_load(&hprog, "libtcmalloc_minimal.dll", pool()); #else apr_dso_load(&hprog, 0, pool()); #endif apr_dso_sym((apr_dso_handle_sym_t*)&MallocExtension_GetNumericProperty, hprog, "MallocExtension_GetNumericProperty"); apr_dso_sym((apr_dso_handle_sym_t*)&MallocExtension_GetStats, hprog, "MallocExtension_GetStats"); initialized = true; } }
void ungrab_dbus_syms() { // should be safe to call regardless of whether we've // actually grabbed syms. if ( sSymDBUSDSOHandleG ) { apr_dso_unload(sSymDBUSDSOHandleG); sSymDBUSDSOHandleG = NULL; } sSymDBUSDSOMemoryPool.destroy(); // NULL-out all of the symbols we'd grabbed #define LL_DBUS_SYM(REQUIRED, DBUSSYM, RTN, ...) do{ll##DBUSSYM = NULL;}while(0) #include "llappviewerlinux_api_dbus_syms_raw.inc" #undef LL_DBUS_SYM sSymsGrabbed = false; }
bool LLAres::process(U64 timeout) { if (!gAPRPoolp) { ll_init_apr(); } ares_socket_t socks[ARES_GETSOCK_MAXNUM]; apr_pollfd_t aprFds[ARES_GETSOCK_MAXNUM]; apr_int32_t nsds = 0; int nactive = 0; int bitmask; bitmask = ares_getsock(chan_, socks, ARES_GETSOCK_MAXNUM); if (bitmask == 0) { return nsds > 0; } apr_status_t status; LLAPRPool pool; status = pool.getStatus() ; ll_apr_assert_status(status); for (int i = 0; i < ARES_GETSOCK_MAXNUM; i++) { if (ARES_GETSOCK_READABLE(bitmask, i)) { aprFds[nactive].reqevents = APR_POLLIN | APR_POLLERR; } else if (ARES_GETSOCK_WRITABLE(bitmask, i)) { aprFds[nactive].reqevents = APR_POLLOUT | APR_POLLERR; } else { continue; } apr_socket_t *aprSock = NULL; status = apr_os_sock_put(&aprSock, (apr_os_sock_t *) &socks[i], pool.getAPRPool()); if (status != APR_SUCCESS) { ll_apr_warn_status(status); return nsds > 0; } aprFds[nactive].desc.s = aprSock; aprFds[nactive].desc_type = APR_POLL_SOCKET; aprFds[nactive].p = pool.getAPRPool(); aprFds[nactive].rtnevents = 0; aprFds[nactive].client_data = &socks[i]; nactive++; } if (nactive > 0) { status = apr_poll(aprFds, nactive, &nsds, timeout); if (status != APR_SUCCESS && status != APR_TIMEUP) { ll_apr_warn_status(status); } for (int i = 0; i < nactive; i++) { int evts = aprFds[i].rtnevents; int ifd = (evts & (APR_POLLIN | APR_POLLERR)) ? *((int *) aprFds[i].client_data) : ARES_SOCKET_BAD; int ofd = (evts & (APR_POLLOUT | APR_POLLERR)) ? *((int *) aprFds[i].client_data) : ARES_SOCKET_BAD; ares_process_fd(chan_, ifd, ofd); } } return nsds > 0; }
int main(int argc, char **argv) { LLError::initForApplication("."); LLError::setFatalFunction(wouldHaveCrashed); LLError::setDefaultLevel(LLError::LEVEL_ERROR); //< *TODO: should come from error config file. Note that we // have a command line option that sets this to debug. #ifdef CTYPE_WORKAROUND ctype_workaround(); #endif LLAPRPool pool; pool.create(); apr_getopt_t* os = NULL; if(APR_SUCCESS != apr_getopt_init(&os, pool(), argc, argv)) { std::cerr << "Unable to initialize the arguments for parsing by apr_getopt()." << std::endl; return 1; } // values used for controlling application bool verbose_mode = false; bool wait_at_exit = false; std::string test_group; // values use for options parsing apr_status_t apr_err; const char* opt_arg = NULL; int opt_id = 0; std::ofstream *output = NULL; const char *touch = NULL; while(true) { apr_err = apr_getopt_long(os, TEST_CL_OPTIONS, &opt_id, &opt_arg); if(APR_STATUS_IS_EOF(apr_err)) break; if(apr_err) { char buf[255]; /* Flawfinder: ignore */ std::cerr << "Error parsing options: " << apr_strerror(apr_err, buf, 255) << std::endl; return 1; } switch (opt_id) { case 'g': test_group.assign(opt_arg); break; case 'h': stream_usage(std::cout, argv[0]); return 0; break; case 'l': stream_groups(std::cout, argv[0]); return 0; case 'v': verbose_mode = true; break; case 'o': output = new std::ofstream; output->open(opt_arg); break; case 's': // --sourcedir tut::sSourceDir = opt_arg; // For convenience, so you can use tut::sSourceDir + "myfile" tut::sSourceDir += '/'; break; case 't': touch = opt_arg; break; case 'w': wait_at_exit = true; break; case 'd': // *TODO: should come from error config file. We set it to // ERROR by default, so this allows full debug levels. LLError::setDefaultLevel(LLError::LEVEL_DEBUG); break; default: stream_usage(std::cerr, argv[0]); return 1; break; } } // run the tests LLTestCallback callback(verbose_mode, output); tut::runner.get().set_callback(&callback); if(test_group.empty()) { tut::runner.get().run_tests(); } else { tut::runner.get().run_tests(test_group); } if (wait_at_exit) { std::cerr << "Waiting for input before exiting..." << std::endl; std::cin.get(); } if (output) { output->close(); delete output; } if (touch) { std::ofstream s; s.open(touch); s << "ok" << std::endl; s.close(); } return 0; }
bool grab_dbus_syms(std::string dbus_dso_name) { if (sSymsGrabbed) { // already have grabbed good syms return TRUE; } bool sym_error = false; bool rtn = false; apr_status_t rv; apr_dso_handle_t *sSymDBUSDSOHandle = NULL; #define LL_DBUS_SYM(REQUIRED, DBUSSYM, RTN, ...) do{rv = apr_dso_sym((apr_dso_handle_sym_t*)&ll##DBUSSYM, sSymDBUSDSOHandle, #DBUSSYM); if (rv != APR_SUCCESS) {INFOMSG("Failed to grab symbol: %s", #DBUSSYM); if (REQUIRED) sym_error = true;} else DEBUGMSG("grabbed symbol: %s from %p", #DBUSSYM, (void*)ll##DBUSSYM);}while(0) //attempt to load the shared library sSymDBUSDSOMemoryPool.create(); #ifdef LL_STANDALONE void *dso_handle = dlopen(dbus_dso_name.c_str(), RTLD_NOW | RTLD_GLOBAL); rv = (!dso_handle)?APR_EDSOOPEN:apr_os_dso_handle_put(&sSymDBUSDSOHandle, dso_handle, sSymDBUSDSOMemoryPool()); if ( APR_SUCCESS == rv ) #else if ( APR_SUCCESS == (rv = apr_dso_load(&sSymDBUSDSOHandle, dbus_dso_name.c_str(), sSymDBUSDSOMemoryPool()) )) #endif { INFOMSG("Found DSO: %s", dbus_dso_name.c_str()); #include "llappviewerlinux_api_dbus_syms_raw.inc" if ( sSymDBUSDSOHandle ) { sSymDBUSDSOHandleG = sSymDBUSDSOHandle; sSymDBUSDSOHandle = NULL; } rtn = !sym_error; } else { INFOMSG("Couldn't load DSO: %s", dbus_dso_name.c_str()); rtn = false; // failure } if (sym_error) { WARNMSG("Failed to find necessary symbols in DBUS-GLIB libraries."); } #undef LL_DBUS_SYM sSymsGrabbed = rtn; if (!sSymsGrabbed) { sSymDBUSDSOMemoryPool.destroy(); } return rtn; }
int LLProcessLauncher::launch(void) { // If there was already a process associated with this object, kill it. kill(); orphan(); int result = 0; int current_wd = -1; // create an argv vector for the child process const char ** fake_argv = new const char *[mLaunchArguments.size() + 2]; // 1 for the executable path, 1 for the NULL terminator int i = 0; // add the executable path fake_argv[i++] = mExecutable.c_str(); // and any arguments for(int j=0; j < mLaunchArguments.size(); j++) fake_argv[i++] = mLaunchArguments[j].c_str(); // terminate with a null pointer fake_argv[i] = NULL; if(!mWorkingDir.empty()) { // save the current working directory current_wd = ::open(".", O_RDONLY); // and change to the one the child will be executed in if (::chdir(mWorkingDir.c_str())) { // chdir failed } } pid_t id; { #ifdef DEBUG_PIPE_CHILD_ERROR_REPORTING // Set up a pipe to the child process for error reporting. apr_file_t* in; apr_file_t* out; LLAPRPool pool; pool.create(); #if(APR_VERSION_MAJOR==1 && APR_VERSION_MINOR>=3 || APR_VERSION_MAJOR>1) apr_status_t status = apr_file_pipe_create_ex(&in, &out, APR_FULL_BLOCK, pool()); #else apr_status_t status = apr_file_pipe_create(&in, &out, pool()); #endif assert(status == APR_SUCCESS); bool success = (status == APR_SUCCESS); if (success) { apr_interval_time_t const timeout = 10000000; // 10 seconds. status = apr_file_pipe_timeout_set(in, timeout); assert(status == APR_SUCCESS); success = (status == APR_SUCCESS); } #endif // DEBUG_PIPE_CHILD_ERROR_REPORTING // flush all buffers before the child inherits them ::fflush(NULL); id = vfork(); if (id == 0) { // child process #ifdef DEBUG_PIPE_CHILD_ERROR_REPORTING // Tell parent process we're about to call execv. write_pipe(out, "CALLING EXECV"); #ifdef _DEBUG char const* display = getenv("DISPLAY"); std::cerr << "Calling ::execv(\"" << mExecutable << '"'; for(int j = 0; j < i; ++j) std::cerr << ", \"" << fake_argv[j] << '"'; std::cerr << ") with DISPLAY=\"" << (display ? display : "NULL") << '"' << std::endl; #endif #endif // DEBUG_PIPE_CHILD_ERROR_REPORTING ::execv(mExecutable.c_str(), (char * const *)fake_argv); #ifdef DEBUG_PIPE_CHILD_ERROR_REPORTING status = APR_FROM_OS_ERROR(apr_get_os_error()); char message[256]; char errbuf[128]; apr_strerror(status, errbuf, sizeof(errbuf)); snprintf(message, sizeof(message), "Child process: execv: %s: %s", mExecutable.c_str(), errbuf); write_pipe(out, message); #ifdef _DEBUG std::cerr << "::execv() failed." << std::endl; #endif #endif // DEBUG_PIPE_CHILD_ERROR_REPORTING // If we reach this point, the exec failed. // Use _exit() instead of exit() per the vfork man page. _exit(0); } // parent process #ifdef DEBUG_PIPE_CHILD_ERROR_REPORTING // Close unused pipe end. apr_file_close(out); if (success) { // Attempt to do error reporting. std::string message = read_pipe(in); success = (message == "CALLING EXECV"); assert(success); if (success) { status = apr_file_pipe_timeout_set(in, 2000000); // Only wait 2 seconds. message = read_pipe(in, true); if (message != "TIMEOUT" && message != "END OF FILE") { // Most likely execv failed. llwarns << message << llendl; assert(false); // Fail in debug mode. } } } // Clean up. apr_file_close(in); #endif // DEBUG_PIPE_CHILD_ERROR_REPORTING } if(current_wd >= 0) { // restore the previous working directory if (::fchdir(current_wd)) { // chdir failed } ::close(current_wd); } delete[] fake_argv; mProcessID = id; // At this point, the child process will have been created (since that's how vfork works -- the child borrowed our execution context until it forked) // If the process doesn't exist at this point, the exec failed. if(!isRunning()) { result = -1; } return result; }