OPTION(DPL_LOG "DPL logs status" ON)
OPTION(WITH_TESTS "Build tests" OFF)
#enable csp policy support
-OPTION(CSP_SUPPORT "Support for csp policy" ON)
+OPTION(CSP_SUPPORT "Support for csp policy" OFF)
IF(CSP_SUPPORT)
ADD_DEFINITIONS("-DCSP_ENABLED")
ENDIF(CSP_SUPPORT)
INSTALL(FILES ${PROJECT_SOURCE_DIR}/data/generic_popup_horizontal.edj
DESTINATION share/edje/ace/
)
+INSTALL(FILES ${CMAKE_SOURCE_DIR}/wrt_env.sh
+ DESTINATION /etc/profile.d/
+ )
ADD_SUBDIRECTORY(src)
ADD_SUBDIRECTORY(po)
+wrt (0.8.16) unstable; urgency=low
+
+ * WRT Process Pool Model
+ * Source clean up (case of launch browser)
+ * Changed order of setting CSP policy
+ * Disable CSP
+
+ -- Tae-Jeong Lee <taejeong.lee@samsung.com> Fri, 22 Mar 2013 19:21:40 +0900
+
wrt (0.8.165) unstable; urgency=low
* JS Global Context PluginModule starting and stoping bug fix
-#git:framework/web/wrt wrt_0.8.165
+#git:framework/web/wrt wrt_0.8.166
Name: wrt
Summary: web runtime
-Version: 0.8.165
+Version: 0.8.166
Release: 1
Group: Development/Libraries
License: Apache License, Version 2.0
%attr(755,root,root) %{_bindir}/wrt-tests-general
/opt/share/widget/tests/general/*
%endif
+%attr(755,root,root) %{_sysconfdir}/profile.d/wrt_env.sh
## wrt-launchpad-daemon #######################################################
%attr(755,root,root) %{_bindir}/wrt_launchpad_daemon
setAutoFullscreenMode();
setBackgroundSupport();
+ // ewk storage_path set
+ ewk_context_storage_path_reset(m_ewkContext);
+
m_initialized = true;
return true;
#include <dpl/wrt-dao-ro/WrtDatabase.h>
#include <dpl/localization/localization_utils.h>
#include <dpl/string.h>
+#include <dpl/wrt-dao-ro/global_config.h>
#include <dpl/wrt-dao-ro/widget_dao_read_only.h>
#include <dpl/utils/mime_type_utils.h>
#include <dpl/localization/LanguageTagsProvider.h>
#include <js_overlay_types.h>
+#include <sys/time.h>
+#include <sys/resource.h>
+#include <privilege-control.h>
+
// URI localization on WebProcess side
#include "bundle_uri_handling.h"
extern "C" {
const char * const VIEWMODE_TYPE_FULLSCREEN = "fullscreen";
const char * const VIEWMODE_TYPE_MAXIMIZED = "maximized";
const std::size_t FILE_BUF_MAX_SIZE = 1024; // bytes
+const std::size_t PLAIN_CHUNK_SIZE = 1008; // bytes
+const unsigned int UID_ROOT = 0;
+const unsigned int DEFAULT_PRIORITY = 0;
+const char * const PRIVILEGE_APP_TYPE = "wgt";
+
static bool m_initWebApp = false;
Tizen::Base::ByteBuffer *DecryptChunkByTrustZone(
m_widgetTizenId = DPL::FromASCIIString(msgString);
WrtDB::WidgetDAOReadOnly dao(m_widgetTizenId);
+
+ // process pool - set app_privilige
+ if (UID_ROOT == getuid())
+ {
+ using namespace WrtDB::GlobalConfig;
+
+ std::string appPath;
+ std::string tzAppId = DPL::ToUTF8String(dao.getTzAppId());
+ std::string tzPkgId = DPL::ToUTF8String(dao.getTizenPkgId());
+
+ appPath = appPath + GetUserInstalledWidgetPath() + "/" +
+ tzPkgId + GetUserWidgetExecPath() + "/" + tzAppId;
+
+ LogDebug("set_app_privilege(" << appPath << ")");
+ set_app_privilege(tzPkgId.c_str(), PRIVILEGE_APP_TYPE, appPath.c_str());
+ }
+
/* This type of message is received when widget is restarting
* (proably in other situation too). Widget restart can be
* called after system language change so language tags have to
WKRelease(urlStr);
WKRelease(retVal);
WKRelease(blockMessage);
+ return WKBundlePagePolicyActionPassThrough;
}
// get scheme string
&Bundle::didReceiveMessageCallback
};
WKBundleSetClient(bundle, &client);
+
+ // process pool - restore process priority
+ if (UID_ROOT == getuid())
+ {
+ setpriority(PRIO_PROCESS, 0, DEFAULT_PRIORITY);
+ }
}
}
// EWK_ENFORCE_POLICY);
//LogInfo("Default policy set");
- DPL::OptionalString policy = m_model->CspPolicy.Get();
+ DPL::OptionalString policy = m_model->CspReportOnlyPolicy.Get();
if (!(policy.IsNull()))
{
- LogDebug("CSP policy present in manifest: " << *policy);
+ LogDebug("CSP report only policy present in manifest: " << *policy);
ewk_view_content_security_policy_set(
- wkView, DPL::ToUTF8String(*policy).c_str(), EWK_ENFORCE_POLICY);
+ wkView, DPL::ToUTF8String(*policy).c_str(), EWK_REPORT_ONLY);
} else {
- LogDebug("Config CSP policy is not present");
+ LogDebug("Config CSP report only policy is not present");
}
- policy = m_model->CspReportOnlyPolicy.Get();
+ policy = m_model->CspPolicy.Get();
+
if (!(policy.IsNull()))
{
- LogDebug("CSP report only policy present in manifest: " << *policy);
+ LogDebug("CSP policy present in manifest: " << *policy);
ewk_view_content_security_policy_set(
- wkView, DPL::ToUTF8String(*policy).c_str(), EWK_REPORT_ONLY);
+ wkView, DPL::ToUTF8String(*policy).c_str(), EWK_ENFORCE_POLICY);
} else {
- LogDebug("Config CSP report only policy is not present");
+ LogDebug("Config CSP policy is not present");
}
+
LogInfo("CSP set.");
#endif
return;
}
- // check if this loading is for blocked url
- if (This->m_blockedUri == url) {
- if (ewk_view_back_possible(This->m_currentEwkView)) {
- // go back to previous page
- LogDebug("go to previous page");
- ewk_view_back(This->m_currentEwkView);
- } else {
- // stop current page
- LogDebug("remove current page");
- ewk_view_stop(This->m_currentEwkView);
- This->m_closedEwkView = This->m_currentEwkView;
- ecore_idler_add(windowCloseIdlerCallback, This);
- }
- This->m_blockedUri = std::string();
- return;
- }
-
DPL::OptionalString jsOptionalString =
ViewModule::PasswordSupport::jsForAutoFillData(url);
if (jsOptionalString.IsNull()) {
Ewk_Policy_Decision* policyDecision =
static_cast<Ewk_Policy_Decision*>(eventInfo);
+ // handle blocked url
+ const char* url = ewk_policy_decision_url_get(policyDecision);
+ if (url && strlen(url) != 0) {
+ if (This->m_blockedUri == url) {
+ LogDebug("Blocked url = " << url);
+ This->m_blockedUri = std::string();
+ ewk_policy_decision_ignore(policyDecision);
+ return;
+ }
+ }
+
if (This->m_schemeSupport->filterURIByScheme(policyDecision,
false,
This->m_model,
${PROJECT_SOURCE_DIR}/src/wrt-client/window_data.cpp
${PROJECT_SOURCE_DIR}/src/wrt-client/splash_screen_support.cpp
${PROJECT_SOURCE_DIR}/src/wrt-client/wrt-client.cpp
+ ${PROJECT_SOURCE_DIR}/src/wrt-launchpad-daemon/src/process_pool.c
)
PKG_CHECK_MODULES(CLIENT_DEP
INCLUDE_DIRECTORIES(
${PROJECT_SOURCE_DIR}/src/wrt-client
${PROJECT_SOURCE_DIR}/src/api_new
+ ${PROJECT_SOURCE_DIR}/src/wrt-launchpad-daemon/include
${CLIENT_DEP_INCLUDE_DIRS}
)
WindowData::WindowData(unsigned long pid, bool manualInit) :
m_win(NULL),
- m_naviBackButton(NULL)
+ m_naviBackButton(NULL),
+ m_initialized(false)
{
m_win = createWindow(pid);
{
Assert(m_win != NULL && "m_win is null");
+ if (m_initialized == true)
+ {
+ LogInfo("Already initilized");
+ return;
+ }
+
// import button theme
elm_theme_overlay_add(NULL, THEME_EDJ_PATH);
evas_object_show(m_navigation);
m_user_layout = createUserLayout(m_navigation);
evas_object_show(m_user_layout);
+
+ m_initialized = true;
}
void WindowData::setEvasObjectForLayout(Evas_Object* evas_object)
Evas_Object* m_naviBackButton;
Evas_Object* m_floatBackButton;
bool m_fullscreen;
+ bool m_initialized;
Evas_Object* createWindow(unsigned long pid);
Evas_Object* createPlatformLayout(Evas_Object* parent);
* limitations under the License.
*/
#include "wrt-client.h"
+#include <aul.h>
+#include <sys/time.h>
+#include <sys/resource.h>
#include <appcore-efl.h>
#include <appcore-common.h>
#include <cstdlib>
#include <dpl/localization/LanguageTagsProvider.h>
#include "webkit/bundles/plugin_module_support.h"
+#include "process_pool.h"
+#include "menu_db_util.h"
+#include "launchpad_util.h"
+
//W3C PACKAGING enviroment variable name
#define W3C_DEBUG_ENV_VARIABLE "DEBUG_LOAD_FINISH"
char const* const ELM_SWALLOW_CONTENT = "elm.swallow.content";
const char* const BUNDLE_PATH = "/usr/lib/wrt-wk2-bundles/libwrt-wk2-bundle.so";
-static Ewk_Context* s_ewk_context = NULL;
+// process pool
+const char* const DUMMY_PROCESS_PATH = "/usr/bin/wrt_launchpad_daemon_candidate";
+static Ewk_Context* s_preparedEwkContext = NULL;
+static WindowData* s_preparedWindowData = NULL;
+static int app_argc = 0;
+static char** app_argv = NULL;
WrtClient::WrtClient(int argc, char **argv) :
Application(argc, argv, "wrt-client", false),
// languageChangedCallback, this);
ADD_PROFILING_POINT("CreateWindow", "start");
- m_windowData.reset(new WindowData(static_cast<unsigned long>(getpid()),
- true));
+ if (s_preparedWindowData == NULL)
+ {
+ m_windowData.reset(new WindowData(static_cast<unsigned long>(getpid()), true));
+ }
+ else
+ {
+ m_windowData.reset(s_preparedWindowData);
+ s_preparedWindowData = NULL;
+ }
ADD_PROFILING_POINT("CreateWindow", "stop");
WRT::UserDelegatesPtr cbs(new WRT::UserDelegates);
ADD_PROFILING_POINT("Create splash screen", "stop");
DPL::OptionalString startUrl = W3CFileLocalization::getStartFile(m_dao);
if (!m_widget->PrepareView(DPL::ToUTF8String(*startUrl),
- m_windowData->m_win, s_ewk_context))
+ m_windowData->m_win, s_preparedEwkContext))
{
DPL::Event::ControllerEventHandler<NextStepEvent>::PostEvent(
NextStepEvent());
m_widget->SetUserDelegates(cbs);
m_widget->Show();
+
m_windowData->emitSignalForUserLayout(EDJE_SHOW_BACKWARD_SIGNAL, "");
+
ADD_PROFILING_POINT("launchStep", "stop");
}
m_widgetState = WidgetState_Stopped;
m_widget->Hide();
m_widget.reset();
- ewk_context_delete(s_ewk_context);
+ ewk_context_delete(s_preparedEwkContext);
WRT::CoreModuleSingleton::Instance().Terminate();
}
if (m_initialized) {
DPL::Application::Quit();
}
+static Eina_Bool proces_pool_fd_handler(void* /*data*/, Ecore_Fd_Handler *handler)
+{
+ int fd = ecore_main_fd_handler_fd_get(handler);
+
+ if (ecore_main_fd_handler_active_get(handler, ECORE_FD_ERROR))
+ {
+ LogDebug("ECORE_FD_ERROR");
+ close(fd);
+ exit(-1);
+ return ECORE_CALLBACK_CANCEL;
+ }
+
+ if (ecore_main_fd_handler_active_get(handler, ECORE_FD_READ))
+ {
+ LogDebug("ECORE_FD_READ");
+ {
+ app_pkt_t* pkt = (app_pkt_t*) malloc(sizeof(char) * AUL_SOCK_MAXBUFF);
+ memset(pkt, 0, AUL_SOCK_MAXBUFF);
+
+ int recv_ret = recv(fd, pkt, AUL_SOCK_MAXBUFF, 0);
+
+ close(fd);
+
+ if (recv_ret == -1)
+ {
+ LogDebug("recv error!");
+ exit(-1);
+ }
+ LogDebug("recv_ret : " << recv_ret << ", pkt->len : " << pkt->len);
+
+ ecore_main_fd_handler_del(handler);
+
+ __wrt_launchpad_main_loop(pkt, app_argv[0], &app_argc, &app_argv);
+
+ free(pkt);
+ }
+
+ ecore_main_loop_quit();
+ return ECORE_CALLBACK_CANCEL;
+ }
+
+ return ECORE_CALLBACK_CANCEL;
+}
+
+
+void set_env()
+{
+ // set evas backend type
+ if (!getenv("ELM_ENGINE"))
+ {
+ if (!setenv("ELM_ENGINE", "gl", 1))
+ {
+ LogDebug("Enable backend");
+ }
+ }
+ else
+ {
+ LogDebug("ELM_ENGINE : " << getenv("ELM_ENGINE"));
+ }
+
+#ifndef TIZEN_PUBLIC
+ setenv("COREGL_FASTPATH", "1", 1);
+#endif
+ setenv("CAIRO_GL_COMPOSITOR", "msaa", 1);
+ setenv("CAIRO_GL_LAZY_FLUSHING", "yes", 1);
+ setenv("ELM_IMAGE_CACHE", "0", 1);
+}
+
+
int main(int argc,
char *argv[])
{
+ // process pool - store arg's value
+ app_argc = argc;
+ app_argv = argv;
+
UNHANDLED_EXCEPTION_HANDLER_BEGIN
{
ADD_PROFILING_POINT("main-entered", "point");
// Set log tagging
DPL::Log::LogSystemSingleton::Instance().SetTag("WRT");
- // set evas backend type
- if (!getenv("ELM_ENGINE")) {
- if (!setenv("ELM_ENGINE", "gl", 1)) {
- LogDebug("Enable backend");
- }
- } else {
- LogDebug("ELM_ENGINE : " << getenv("ELM_ENGINE"));
- }
-
- #ifndef TIZEN_PUBLIC
- setenv("COREGL_FASTPATH", "1", 1);
- #endif
- setenv("CAIRO_GL_COMPOSITOR", "msaa", 1);
- setenv("CAIRO_GL_LAZY_FLUSHING", "yes", 1);
- setenv("ELM_IMAGE_CACHE", "0", 1);
+ // Set environment variables
+ set_env();
- // This code is to fork a web process without exec.
- std::string tizenId = WrtClient::getTizenIdFromArgument(argc, argv);
+ if (argc > 1 && argv[1] != NULL && !strcmp(argv[1], "-d"))
+ {
+ LogInfo("Entered dummy process mode");
+ sprintf(argv[0], "%s ",
+ DUMMY_PROCESS_PATH);
- if (!tizenId.empty()) {
- LogDebug("Launching by fork mode");
- // Language env setup
+ LogInfo("Prepare ewk_context");
appcore_set_i18n("wrt-client", NULL);
ewk_init();
ewk_set_arguments(argc, argv);
setenv("WRT_LAUNCHING_PERFORMANCE", "1", 1);
- s_ewk_context = ewk_context_new_with_injected_bundle_path(
- BUNDLE_PATH);
+ s_preparedEwkContext = ewk_context_new_with_injected_bundle_path(BUNDLE_PATH);
+
+ int client_fd = __connect_process_pool_server();
+
+ if (client_fd == -1)
+ {
+ LogInfo("Connecting process_pool_server was failed!");
+ exit(-1);
+ }
+
+ LogInfo("Prepare window_data");
+ LogInfo("elm_init()");
+ elm_init(argc, argv);
+ LogInfo("WindowData()");
+ s_preparedWindowData = new WindowData(static_cast<unsigned long>(getpid()));
- // plugin init
- PluginModuleSupport::init(s_ewk_context, tizenId);
+ ecore_main_fd_handler_add(client_fd, ECORE_FD_READ, proces_pool_fd_handler, NULL, NULL, NULL);
+ ecore_main_fd_handler_add(client_fd, ECORE_FD_ERROR, proces_pool_fd_handler, NULL, NULL, NULL);
+
+ setpriority(PRIO_PROCESS, 0, 0);
+
+ LogDebug("ecore_main_loop_begin()");
+ ecore_main_loop_begin();
+ LogDebug("ecore_main_loop_begin()_end");
+
+ std::string tizenId = WrtClient::getTizenIdFromArgument(argc, argv);
+ PluginModuleSupport::init(s_preparedEwkContext, tizenId);
+
+ }
+ else
+ {
+ // This code is to fork a web process without exec.
+ std::string tizenId = WrtClient::getTizenIdFromArgument(argc, argv);
+
+ if (!tizenId.empty())
+ {
+ LogDebug("Launching by fork mode");
+ // Language env setup
+ appcore_set_i18n("wrt-client", NULL);
+ ewk_init();
+ ewk_set_arguments(argc, argv);
+ setenv("WRT_LAUNCHING_PERFORMANCE", "1", 1);
+ s_preparedEwkContext = ewk_context_new_with_injected_bundle_path(
+ BUNDLE_PATH);
+
+ // plugin init
+ PluginModuleSupport::init(s_preparedEwkContext, tizenId);
+ }
}
// Output on stdout will be flushed after every newline character,
// the output may not be flushed).
setlinebuf(stdout);
- WrtClient app(argc, argv);
+ WrtClient app(app_argc, app_argv);
ADD_PROFILING_POINT("Before appExec", "point");
int ret = app.Exec();
src/simple_util.c
launchpad_src/launchpad.c
launchpad_src/util_x.c
+ src/process_pool.c
)
#link libraries
* limitations under the License.
*/
+#ifndef __ACCESS_CONTROL_H_
+#define __ACCESS_CONTROL_H_
+
#ifdef DAC_ACTIVATE
#include <privilege-control.h>
#endif
+#endif //__ACCESS_CONTROL_H_
+
* limitations under the License.
*/
+#ifndef __LAUNCHPAD_CONFIG_H_
+#define __LAUNCHPAD_CONFIG_H_
+
#define LAUNCHPAD_LOG
#define DAC_ACTIVATE
#define PRELOAD_ACTIVATE
/*#define HEAPDGB_ACTIVATE*/
/*#define PERF_ACTIVATE*/
+#endif // __LAUNCHPAD_CONFIG_H_
\ No newline at end of file
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+#ifndef __GL_H_
+#define __GL_H_
#ifdef GL_ACTIVATE
-
#define USE_ENGINE(engine) setenv("ELM_ENGINE", engine, 1);
-
#else
-
#define USE_ENGINE(engine)
-
#endif
+#endif //__GL_H_
\ No newline at end of file
--- /dev/null
+/*
+ * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+/**
+ * @file launchpad_util.h
+ * @author Tae-Jeong Lee (taejeong.lee@samsung.com)
+ * @version 0.1
+ * @brief Api library to support launchpad operation.
+ */
+
+#ifndef __LAUNCHPAD_UTIL_H_
+#define __LAUNCHPAD_UTIL_H_
+
+#include <aul.h>
+#include <bundle.h>
+#include <privilege-control.h>
+#include <sys/prctl.h>
+
+#include "config.h"
+#include "gl.h"
+#include "app_sock.h"
+#include "menu_db_util.h"
+#include "simple_util.h"
+#include "access_control.h"
+
+#define _static_ static inline
+#define WRT_AUL_PR_NAME 16
+#define PKG_ID_LENGTH 11
+#define SDK_CODE_COVERAGE "CODE_COVERAGE"
+#define SDK_DYNAMIC_ANALYSIS "DYNAMIC_ANALYSIS"
+#define PATH_DA_SO "/home/developer/sdk_tools/da/da_probe.so"
+#define PATH_APP_ROOT "/opt/usr/apps"
+#define PATH_DATA "/data"
+
+// Prototype
+_static_ char** __create_argc_argv(bundle * kb, int *margc);
+_static_ void __set_sdk_env(app_info_from_db* menu_info, char* str);
+_static_ int __parser(const char *arg, char *out, int out_size);
+_static_ void __modify_bundle(bundle * kb, int caller_pid, app_info_from_db * menu_info, int cmd);
+_static_ void __set_oom();
+_static_ void __set_env(app_info_from_db * menu_info, bundle * kb);
+_static_ int __wrt_prepare_exec(const char *pkg_name, const char *app_path, app_info_from_db * menu_info, bundle * kb);
+_static_ void __wrt_launchpad_main_loop(app_pkt_t* pkt, char* out_app_path, int* out_argc, char ***out_argv);
+
+// Implementation
+
+_static_ char** __create_argc_argv(bundle * kb, int *margc)
+{
+ char **argv;
+ int argc;
+
+ argc = bundle_export_to_argv(kb, &argv);
+
+ *margc = argc;
+ return argv;
+}
+
+_static_ void __set_sdk_env(app_info_from_db* menu_info, char* str)
+{
+ char buf[MAX_LOCAL_BUFSZ];
+ int ret;
+
+ _D("key : %s / value : %s", AUL_K_SDK, str);
+ /* http://gcc.gnu.org/onlinedocs/gcc/Cross_002dprofiling.html*/
+ /* GCOV_PREFIX contains the prefix to add to the absolute paths in the
+ *object file. */
+ /* Prefix can be absolute, or relative. The default is no prefix.
+ * */
+ /* GCOV_PREFIX_STRIP indicates the how many initial directory names */
+ /* to stripoff the hardwired absolute paths. Default value is 0. */
+ if (strncmp(str, SDK_CODE_COVERAGE, strlen(str)) == 0) {
+ snprintf(buf,
+ MAX_LOCAL_BUFSZ,
+ PATH_APP_ROOT "/%s"PATH_DATA,
+ _get_pkgname(menu_info));
+ ret = setenv("GCOV_PREFIX", buf, 1);
+ _D("GCOV_PREFIX : %d", ret);
+ ret = setenv("GCOV_PREFIX_STRIP", "4096", 1);
+ _D("GCOV_PREFIX_STRIP : %d", ret);
+ } else if (strncmp(str, SDK_DYNAMIC_ANALYSIS, strlen(str)) == 0) {
+ ret = setenv("LD_PRELOAD", PATH_DA_SO, 1);
+ _D("LD_PRELOAD : %d", ret);
+ }
+}
+
+
+/*
+ * Parsing original app path to retrieve default bundle
+ *
+ * -1 : Invalid sequence
+ * -2 : Buffer overflow
+ *
+ */
+_static_ int __parser(const char *arg, char *out, int out_size)
+{
+ register int i;
+ int state = 1;
+ char *start_out = out;
+
+ if (arg == NULL || out == NULL) {
+ /* Handles null buffer*/
+ return 0;
+ }
+
+ for (i = 0; out_size > 1; i++) {
+ switch (state) {
+ case 1:
+ switch (arg[i]) {
+ case ' ':
+ case '\t':
+ state = 5;
+ break;
+ case '\0':
+ state = 7;
+ break;
+ case '\"':
+ state = 2;
+ break;
+ case '\\':
+ state = 4;
+ break;
+ default:
+ *out = arg[i];
+ out++;
+ out_size--;
+ break;
+ }
+ break;
+ case 2: /* escape start*/
+ switch (arg[i]) {
+ case '\0':
+ state = 6;
+ break;
+ case '\"':
+ state = 1;
+ break;
+ default:
+ *out = arg[i];
+ out++;
+ out_size--;
+ break;
+ }
+ break;
+ case 4: /* character escape*/
+ if (arg[i] == '\0') {
+ state = 6;
+ } else {
+ *out = arg[i];
+ out++;
+ out_size--;
+ state = 1;
+ }
+ break;
+ case 5: /* token*/
+ if (out != start_out) {
+ *out = '\0';
+ out_size--;
+ return i;
+ }
+ i--;
+ state = 1;
+ break;
+ case 6:
+ return -1; /* error*/
+ case 7: /* terminate*/
+ *out = '\0';
+ out_size--;
+ return 0;
+ default:
+ state = 6;
+ break; /* error*/
+ }
+ }
+
+ if (out_size == 1) {
+ *out = '\0';
+ }
+ /* Buffer overflow*/
+ return -2;
+}
+
+
+_static_ void __modify_bundle(bundle * kb, int caller_pid,
+ app_info_from_db * menu_info, int cmd)
+{
+ // warning: unused parameter
+ caller_pid = caller_pid;
+
+ bundle_del(kb, AUL_K_PKG_NAME);
+ bundle_del(kb, AUL_K_EXEC);
+ bundle_del(kb, AUL_K_PACKAGETYPE);
+ bundle_del(kb, AUL_K_HWACC);
+
+ /* Parse app_path to retrieve default bundle*/
+ if (cmd == APP_START || cmd == APP_START_RES || cmd == APP_OPEN || cmd ==
+ APP_RESUME)
+ {
+ char *ptr;
+ char exe[MAX_PATH_LEN];
+ int flag;
+
+ ptr = _get_original_app_path(menu_info);
+
+ flag = __parser(ptr, exe, sizeof(exe));
+ if (flag > 0) {
+ char key[256];
+ char value[256];
+
+ ptr += flag;
+ _D("parsing app_path: EXEC - %s\n", exe);
+
+ do {
+ flag = __parser(ptr, key, sizeof(key));
+ if (flag <= 0) {
+ break;
+ }
+ ptr += flag;
+
+ flag = __parser(ptr, value, sizeof(value));
+ if (flag < 0) {
+ break;
+ }
+ ptr += flag;
+
+ /*bundle_del(kb, key);*/
+ bundle_add(kb, key, value);
+ } while (flag > 0);
+ } else if (flag == 0) {
+ _D("parsing app_path: No arguments\n");
+ } else {
+ _D("parsing app_path: Invalid argument\n");
+ }
+ }
+}
+
+
+_static_ void __set_oom()
+{
+ char buf[MAX_LOCAL_BUFSZ];
+ FILE *fp;
+
+ /* we should reset oomadj value as default because child
+ * inherits from parent oom_adj*/
+ snprintf(buf, MAX_LOCAL_BUFSZ, "/proc/%d/oom_adj", getpid());
+ fp = fopen(buf, "w");
+ if (fp == NULL) {
+ return;
+ }
+ fprintf(fp, "%d", -16);
+ fclose(fp);
+}
+
+_static_ void __set_env(app_info_from_db * menu_info, bundle * kb)
+{
+ const char *str;
+ const char **str_array;
+ int len;
+ int i;
+
+ setenv("PKG_NAME", _get_pkgname(menu_info), 1);
+
+ USE_ENGINE("gl")
+
+ str = bundle_get_val(kb, AUL_K_STARTTIME);
+ if (str != NULL) {
+ setenv("APP_START_TIME", str, 1);
+ }
+
+ if (bundle_get_type(kb, AUL_K_SDK) & BUNDLE_TYPE_ARRAY) {
+ str_array = bundle_get_str_array(kb, AUL_K_SDK, &len);
+ if (str_array != NULL) {
+ for (i = 0; i < len; i++) {
+ _D("index : [%d]", i);
+ __set_sdk_env(menu_info, (char *)str_array[i]);
+ }
+ }
+ } else {
+ str = bundle_get_val(kb, AUL_K_SDK);
+ if (str != NULL) {
+ __set_sdk_env(menu_info, (char *)str);
+ }
+ }
+ if (menu_info->hwacc != NULL) {
+ setenv("HWACC", menu_info->hwacc, 1);
+ }
+}
+
+_static_ int __wrt_prepare_exec(const char *pkg_name,
+ const char *app_path, app_info_from_db * menu_info,
+ bundle * kb)
+{
+ const char *file_name;
+ char process_name[WRT_AUL_PR_NAME];
+
+ /* SET PRIVILEGES*/
+ char pkg_id[PKG_ID_LENGTH];
+ memset(pkg_id, '\0', PKG_ID_LENGTH);
+ snprintf(pkg_id, PKG_ID_LENGTH, "%s", pkg_name);
+
+ if (__set_access(pkg_id, menu_info->pkg_type, app_path) < 0) {
+ _D("fail to set privileges - check your package's credential\n");
+ return -1;
+ }
+
+ /* SET PROCESS NAME*/
+ if (app_path == NULL) {
+ _D("app_path should not be NULL - check menu db");
+ return -1;
+ }
+ file_name = strrchr(app_path, '/') + 1;
+ if (file_name == NULL) {
+ _D("can't locate file name to execute");
+ return -1;
+ }
+ memset(process_name, '\0', WRT_AUL_PR_NAME);
+ snprintf(process_name, WRT_AUL_PR_NAME, "%s", file_name);
+ prctl(PR_SET_NAME, process_name);
+
+ /* SET ENVIROMENT*/
+ __set_env(menu_info, kb);
+
+ return 0;
+}
+
+_static_ void __wrt_launchpad_main_loop(app_pkt_t* pkt, char* out_app_path, int* out_argc, char ***out_argv)
+
+{
+ bundle *kb = NULL;
+ app_info_from_db *menu_info = NULL;
+
+ const char *pkg_name = NULL;
+ const char *app_path = NULL;
+ struct ucred cr;
+
+ kb = bundle_decode(pkt->data, pkt->len);
+ if (!kb) {
+ _E("bundle decode error");
+ exit(-1);
+ }
+
+ pkg_name = bundle_get_val(kb, AUL_K_PKG_NAME);
+ _D("pkg name : %s", pkg_name);
+
+ menu_info = _get_app_info_from_bundle_by_pkgname(pkg_name, kb);
+ if (menu_info == NULL) {
+ _D("such pkg no found");
+ exit(-1);
+ }
+
+ app_path = _get_app_path(menu_info);
+
+ if (app_path == NULL) {
+ _E("app_path is NULL");
+ exit(-1);
+ }
+
+ if (app_path[0] != '/') {
+ _E("app_path is not absolute path");
+ exit(-1);
+ }
+
+ __modify_bundle(kb, cr.pid, menu_info, pkt->cmd);
+ pkg_name = _get_pkgname(menu_info);
+ _D("pkg name : %s", pkg_name);
+
+ __wrt_prepare_exec(pkg_name, app_path, menu_info, kb);
+
+ if (out_app_path != NULL && out_argc != NULL && out_argv != NULL)
+ {
+ int i;
+
+ sprintf(out_app_path, "%s", app_path);
+
+ *out_argv = __create_argc_argv(kb, out_argc);
+ (*out_argv)[0] = out_app_path;
+
+ for (i = 0; i < *out_argc; i++)
+ {
+ _D("input argument %d : %s##", i, (*out_argv)[i]);
+ }
+ }
+ else
+ {
+ exit(-1);
+ }
+
+
+#if 0 // intentional
+ if (menu_info != NULL) {
+ _free_app_info_from_db(menu_info);
+ }
+
+ if (kb != NULL) {
+ bundle_free(kb);
+ }
+#endif
+}
+
+#endif // __LAUNCHPAD_UTIL_H_
* limitations under the License.
*/
+#ifndef __MENU_DB_UTIL_H_
+#define __MENU_DB_UTIL_H_
+
#include <ail.h>
#include <string.h>
#include "simple_util.h"
free(menu_info->app_path);
menu_info->app_path = NULL;
} else if (path_len > 0) {
- char *tmp_app_path = malloc(sizeof(char) * (path_len + 1));
+ char *tmp_app_path = (char *)malloc(sizeof(char) * (path_len + 1));
if (tmp_app_path == NULL) {
return NULL;
}
ail_error_e ret;
char *str = NULL;
- menu_info = calloc(1, sizeof(app_info_from_db));
+ menu_info = (app_info_from_db *)calloc(1, sizeof(app_info_from_db));
if (menu_info == NULL) {
return NULL;
}
return NULL;
}
- menu_info = calloc(1, sizeof(app_info_from_db));
+ menu_info = (app_info_from_db *)calloc(1, sizeof(app_info_from_db));
if (menu_info == NULL) {
return NULL;
}
return menu_info;
}
+
+static inline app_info_from_db *_get_app_info_from_bundle_by_pkgname(
+ const char *pkgname, bundle *kb)
+{
+ app_info_from_db *menu_info;
+
+ menu_info = (app_info_from_db*)calloc(1, sizeof(app_info_from_db));
+ if (menu_info == NULL) {
+ return NULL;
+ }
+
+ menu_info->pkg_name = strdup(pkgname);
+ menu_info->app_path = strdup(bundle_get_val(kb, AUL_K_EXEC));
+ if (menu_info->app_path != NULL) {
+ menu_info->original_app_path = strdup(menu_info->app_path);
+ }
+ menu_info->pkg_type = strdup(bundle_get_val(kb, AUL_K_PACKAGETYPE));
+ menu_info->hwacc = strdup(bundle_get_val(kb, AUL_K_HWACC));
+
+ if (!_get_app_path(menu_info)) {
+ _free_app_info_from_db(menu_info);
+ return NULL;
+ }
+
+ return menu_info;
+}
+#endif //__MENU_DB_UTIL_H_
\ No newline at end of file
--- /dev/null
+/*
+ * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+/**
+ * @file process_pool.h
+ * @author Tae-Jeong Lee (taejeong.lee@samsung.com)
+ * @version 0.1
+ * @brief process pool socket api prototypes
+ */
+
+#ifndef __PROCESS_POOL_H_
+#define __PROCESS_POOL_H_
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif //__cplusplus
+
+#include <app_sock.h>
+
+int __create_process_pool_server();
+int __connect_process_pool_server();
+int __accept_dummy_process(int server_fd, int* out_client_fd, int* out_client_pid);
+void __refuse_dummy_process(int server_fd);
+int __send_pkt_raw_data(int client_fd, app_pkt_t* pkt);
+
+#ifdef __cplusplus
+}
+#endif //__cplusplus
+
+#endif //__PROCESS_POOL_H_
+
#include <sys/wait.h>
#include <poll.h>
#include <sys/prctl.h>
+#include <sys/time.h>
+#include <sys/resource.h>
#include <malloc.h>
#include "app_sock.h"
#include <app-checker.h>
#include <sqlite3.h>
+#include "process_pool.h"
+#include "launchpad_util.h"
+
#define _static_ static inline
-#define POLLFD_MAX 1
-#define SQLITE_FLUSH_MAX (1048576) /* (1024*1024) */
-#define AUL_POLL_CNT 15
-#define AUL_PR_NAME 16
-#define PKG_ID_LENGTH 11
-#define PATH_APP_ROOT "/opt/usr/apps"
-#define PATH_DATA "/data"
-#define SDK_CODE_COVERAGE "CODE_COVERAGE"
-#define SDK_DYNAMIC_ANALYSIS "DYNAMIC_ANALYSIS"
-#define PATH_DA_SO "/home/developer/sdk_tools/da/da_probe.so"
+#define SQLITE_FLUSH_MAX (1048576) /* (1024*1024) */
+#define AUL_POLL_CNT 15
+#define AUL_PR_NAME 16
+#define PKG_ID_LENGTH 11
+
+#define EXEC_DUMMY_EXPIRED 5
+#define DIFF(a,b) (((a)>(b))?(a)-(b):(b)-(a))
+#define WRT_CLIENT_PATH "/usr/bin/wrt-client"
+#define LOWEST_PRIO 20
+#define DUMMY_NONE 0
static char *launchpad_cmdline;
static int initialized = 0;
+static int dummy_process_pid = DUMMY_NONE;
+static int dummy_process_fd = -1;
+static int last_dummy_exec_time = 0;
+static int process_pool_disable = 0;
-_static_ void __set_oom();
-_static_ void __set_env(app_info_from_db * menu_info, bundle * kb);
_static_ int __prepare_exec(const char *pkg_name,
const char *app_path, app_info_from_db * menu_info,
bundle * kb);
_static_ char **__create_argc_argv(bundle * kb, int *margc);
_static_ int __normal_fork_exec(int argc, char **argv);
_static_ void __real_launch(const char *app_path, bundle * kb);
-static inline int __parser(const char *arg, char *out, int out_size);
-_static_ void __modify_bundle(bundle * kb, int caller_pid,
- app_info_from_db * menu_info, int cmd);
+_static_ int __dummy_launch(int dummy_client_fd, app_pkt_t* pkt);
_static_ int __child_raise_win_by_x(int pid, void *priv);
_static_ int __raise_win_by_x(int pid);
_static_ int __send_to_sigkill(int pid);
_static_ int __resume_app(int pid);
_static_ void __real_send(int clifd, int ret);
_static_ void __send_result_to_caller(int clifd, int ret);
-_static_ void __launchpad_main_loop(int main_fd);
+_static_ void __launchpad_exec_dummy(int main_fd, int pool_fd, int client_fd);
+_static_ void __launchpad_main_loop(int main_fd, int pool_fd);
_static_ int __launchpad_pre_init(int argc, char **argv);
_static_ int __launchpad_post_init();
extern ail_error_e ail_db_close(void);
-_static_ void __set_oom()
-{
- char buf[MAX_LOCAL_BUFSZ];
- FILE *fp;
-
- /* we should reset oomadj value as default because child
- * inherits from parent oom_adj*/
- snprintf(buf, MAX_LOCAL_BUFSZ, "/proc/%d/oom_adj", getpid());
- fp = fopen(buf, "w");
- if (fp == NULL) {
- return;
- }
- fprintf(fp, "%d", -16);
- fclose(fp);
-}
-
-_static_ void __set_sdk_env(app_info_from_db* menu_info, char* str)
-{
- char buf[MAX_LOCAL_BUFSZ];
- int ret;
-
- _D("key : %s / value : %s", AUL_K_SDK, str);
- /* http://gcc.gnu.org/onlinedocs/gcc/Cross_002dprofiling.html*/
- /* GCOV_PREFIX contains the prefix to add to the absolute paths in the
- *object file. */
- /* Prefix can be absolute, or relative. The default is no prefix.
- * */
- /* GCOV_PREFIX_STRIP indicates the how many initial directory names */
- /* to stripoff the hardwired absolute paths. Default value is 0. */
- if (strncmp(str, SDK_CODE_COVERAGE, strlen(str)) == 0) {
- snprintf(buf,
- MAX_LOCAL_BUFSZ,
- PATH_APP_ROOT "/%s"PATH_DATA,
- _get_pkgname(menu_info));
- ret = setenv("GCOV_PREFIX", buf, 1);
- _D("GCOV_PREFIX : %d", ret);
- ret = setenv("GCOV_PREFIX_STRIP", "4096", 1);
- _D("GCOV_PREFIX_STRIP : %d", ret);
- } else if (strncmp(str, SDK_DYNAMIC_ANALYSIS, strlen(str)) == 0) {
- ret = setenv("LD_PRELOAD", PATH_DA_SO, 1);
- _D("LD_PRELOAD : %d", ret);
- }
-}
-
-_static_ void __set_env(app_info_from_db * menu_info, bundle * kb)
-{
- const char *str;
-
- setenv("PKG_NAME", _get_pkgname(menu_info), 1);
-
- USE_ENGINE("gl")
-
- str = bundle_get_val(kb, AUL_K_STARTTIME);
- if (str != NULL) {
- setenv("APP_START_TIME", str, 1);
- }
-
- if (bundle_get_type(kb, AUL_K_SDK) & BUNDLE_TYPE_ARRAY) {
- int len;
- const char **str_array;
- str_array = bundle_get_str_array(kb, AUL_K_SDK, &len);
- if (str_array != NULL) {
- int i;
- for (i = 0; i < len; i++) {
- _D("index : [%d]", i);
- __set_sdk_env(menu_info, (char *)str_array[i]);
- }
- }
- } else {
- str = bundle_get_val(kb, AUL_K_SDK);
- if (str != NULL) {
- __set_sdk_env(menu_info, (char *)str);
- }
- }
- if (menu_info->hwacc != NULL) {
- setenv("HWACC", menu_info->hwacc, 1);
- }
-}
-
_static_ int __prepare_exec(const char *pkg_name,
const char *app_path, app_info_from_db * menu_info,
bundle * kb)
_D("fail to set privileges - check your package's credential\n");
return -1;
}
+
/* SET DUMPABLE - for coredump*/
prctl(PR_SET_DUMPABLE, 1);
return ret;
}
-_static_ char **__create_argc_argv(bundle * kb, int *margc)
-{
- char **argv;
- int argc;
-
- argc = bundle_export_to_argv(kb, &argv);
-
- *margc = argc;
- return argv;
-}
-
_static_ int __normal_fork_exec(int argc, char **argv)
{
_D("start real fork and exec\n");
__normal_fork_exec(app_argc, app_argv);
}
-/*
- * Parsing original app path to retrieve default bundle
- *
- * -1 : Invalid sequence
- * -2 : Buffer overflow
- *
- */
-static inline int __parser(const char *arg, char *out, int out_size)
-{
- register int i;
- int state = 1;
- char *start_out = out;
-
- if (arg == NULL || out == NULL) {
- /* Handles null buffer*/
- return 0;
- }
-
- for (i = 0; out_size > 1; i++) {
- switch (state) {
- case 1:
- switch (arg[i]) {
- case ' ':
- case '\t':
- state = 5;
- break;
- case '\0':
- state = 7;
- break;
- case '\"':
- state = 2;
- break;
- case '\\':
- state = 4;
- break;
- default:
- *out = arg[i];
- out++;
- out_size--;
- break;
- }
- break;
- case 2: /* escape start*/
- switch (arg[i]) {
- case '\0':
- state = 6;
- break;
- case '\"':
- state = 1;
- break;
- default:
- *out = arg[i];
- out++;
- out_size--;
- break;
- }
- break;
- case 4: /* character escape*/
- if (arg[i] == '\0') {
- state = 6;
- } else {
- *out = arg[i];
- out++;
- out_size--;
- state = 1;
- }
- break;
- case 5: /* token*/
- if (out != start_out) {
- *out = '\0';
- out_size--;
- return i;
- }
- i--;
- state = 1;
- break;
- case 6:
- return -1; /* error*/
- case 7: /* terminate*/
- *out = '\0';
- out_size--;
- return 0;
- default:
- state = 6;
- break; /* error*/
- }
- }
-
- if (out_size == 1) {
- *out = '\0';
- }
- /* Buffer overflow*/
- return -2;
-}
-
-_static_ void __modify_bundle(bundle * kb, int caller_pid,
- app_info_from_db * menu_info, int cmd)
+_static_ int __dummy_launch(int dummy_client_fd, app_pkt_t* pkt)
{
- // warning: unused parameter
- (void)caller_pid;
-
- bundle_del(kb, AUL_K_PKG_NAME);
- bundle_del(kb, AUL_K_EXEC);
- bundle_del(kb, AUL_K_PACKAGETYPE);
- bundle_del(kb, AUL_K_HWACC);
-
- /* Parse app_path to retrieve default bundle*/
- if (cmd == APP_START || cmd == APP_START_RES || cmd == APP_OPEN || cmd ==
- APP_RESUME)
- {
- char *ptr;
- char exe[MAX_PATH_LEN];
- int flag;
-
- ptr = _get_original_app_path(menu_info);
-
- flag = __parser(ptr, exe, sizeof(exe));
- if (flag > 0) {
- char key[256];
- char value[256];
-
- ptr += flag;
- _D("parsing app_path: EXEC - %s\n", exe);
-
- do {
- flag = __parser(ptr, key, sizeof(key));
- if (flag <= 0) {
- break;
- }
- ptr += flag;
-
- flag = __parser(ptr, value, sizeof(value));
- if (flag < 0) {
- break;
- }
- ptr += flag;
-
- /*bundle_del(kb, key);*/
- bundle_add(kb, key, value);
- } while (flag > 0);
- } else if (flag == 0) {
- _D("parsing app_path: No arguments\n");
- } else {
- _D("parsing app_path: Invalid argument\n");
- }
- }
+ return __send_pkt_raw_data(dummy_client_fd, pkt);
}
_static_ int __child_raise_win_by_x(int pid, void *priv)
return;
}
-static app_info_from_db *_get_app_info_from_bundle_by_pkgname(
- const char *pkgname, bundle *kb)
+_static_ void __launchpad_exec_dummy(int main_fd, int pool_fd, int client_fd)
{
- app_info_from_db *menu_info;
+ int pid;
- menu_info = calloc(1, sizeof(app_info_from_db));
- if (menu_info == NULL) {
- return NULL;
- }
+ last_dummy_exec_time = time(NULL);
- menu_info->pkg_name = strdup(pkgname);
- menu_info->app_path = strdup(bundle_get_val(kb, AUL_K_EXEC));
- if (menu_info->app_path != NULL) {
- menu_info->original_app_path = strdup(menu_info->app_path);
- }
- menu_info->pkg_type = strdup(bundle_get_val(kb, AUL_K_PACKAGETYPE));
- menu_info->hwacc = strdup(bundle_get_val(kb, AUL_K_HWACC));
+ pid = fork();
- if (!_get_app_path(menu_info)) {
- _free_app_info_from_db(menu_info);
- return NULL;
- }
+ if (pid == 0) // child
+ {
+ setpriority(PRIO_PROCESS, 0, LOWEST_PRIO);
+ _D("Launch dummy process...");
+
+ //temp - this requires some optimization.
+ sleep(1);
+ _D("sleeping 1sec...");
+
+ /* Set new session ID & new process group ID*/
+ /* In linux, child can set new session ID without check permission */
+ /* TODO : should be add to check permission in the kernel*/
+ setsid();
+
+ /* SET OOM*/
+ __set_oom();
+
+
+ if (main_fd != -1)
+ {
+ close(main_fd);
+ }
+
+ if (pool_fd != -1)
+ {
+ close(pool_fd);
+ }
+
+ if (client_fd != -1)
+ {
+ close(client_fd);
+ }
+
+ __signal_unset_sigchld();
+ __signal_fini();
+
+ /* SET DUMPABLE - for coredump*/
+ prctl(PR_SET_DUMPABLE, 1);
+
+ {
+ void *handle = NULL;
+ int (*dl_main) (int, char **);
+
+ handle = dlopen(WRT_CLIENT_PATH, RTLD_NOW | RTLD_GLOBAL);
+
+ if (handle == NULL)
+ {
+ _E("dlopen failed.");
+ exit(-1);
+ }
+
+ dl_main = dlsym(handle, "main");
+
+ sprintf(g_argv[1], "%s", "-d");
+
+ if (dl_main != NULL)
+ {
+ dl_main(g_argc, g_argv);
+ }
+ else
+ {
+ _E("dlsym not founded. bad preloaded app - check fpie pie");
+ }
- return menu_info;
+ exit(0);
+ }
+ }
}
-_static_ void __launchpad_main_loop(int main_fd)
+_static_ void __launchpad_main_loop(int main_fd, int pool_fd)
{
bundle *kb = NULL;
app_pkt_t *pkt = NULL;
PERF("get package information & modify bundle done");
+ if (dummy_process_pid != DUMMY_NONE)
+ {
+ snprintf(sock_path, UNIX_PATH_MAX, "%s/%d", AUL_SOCK_PREFIX, dummy_process_pid);
+ unlink(sock_path);
+
+ __dummy_launch(dummy_process_fd, pkt);
+
+ pid = dummy_process_pid;
+ is_real_launch = 1;
+ close(dummy_process_fd);
+
+ dummy_process_pid = DUMMY_NONE;
+ dummy_process_fd = -1;
+
+ /* Temporary log: launch time checking */
+ LOG(LOG_DEBUG, "LAUNCH", "[%s:Platform:launchpad:done]", app_path);
+
+ __launchpad_exec_dummy(main_fd, pool_fd, clifd);
+
+ _D("==> dummy launch pid : %d %s\n", pid, app_path);
+ }
+ else
{
pid = fork();
- if (pid == 0) {
+
+ if (pid == 0)
+ {
PERF("fork done");
_E("lock up test log(no error) : fork done");
int main(int argc, char **argv)
{
- int main_fd;
+ enum {
+ LAUNCH_PAD = 0,
+ POOL_SERVER,
+ DUMMY_PROCESS,
+ POLLFD_MAX
+ };
+
+ int main_fd = -1, pool_fd = -1;
struct pollfd pfds[POLLFD_MAX];
- int i;
+
+ memset(pfds, 0x00, sizeof(pfds));
+
+ // process pool feature disable
+ if (getenv("WRT_PROCESS_POOL_DISABLE"))
+ {
+ process_pool_disable = 1;
+ }
/* init without concerning X & EFL*/
main_fd = __launchpad_pre_init(argc, argv);
- if (main_fd < 0) {
+
+ if (main_fd < 0)
+ {
_E("launchpad pre init failed");
- exit(-1);
+ goto exit_main;
+ }
+
+ pfds[LAUNCH_PAD].fd = main_fd;
+ pfds[LAUNCH_PAD].events = POLLIN;
+ pfds[LAUNCH_PAD].revents = 0;
+
+ pool_fd = __create_process_pool_server();
+
+ if (pool_fd == -1)
+ {
+ _E("Error creationg pool server!");
+ goto exit_main;
}
- pfds[0].fd = main_fd;
- pfds[0].events = POLLIN;
- pfds[0].revents = 0;
+ pfds[POOL_SERVER].fd = pool_fd;
+ pfds[POOL_SERVER].events = POLLIN;
+ pfds[POOL_SERVER].revents = 0;
- while (1) {
- if (poll(pfds, POLLFD_MAX, -1) < 0) {
+ while (1)
+ {
+ if (dummy_process_pid == DUMMY_NONE)
+ {
+ pfds[DUMMY_PROCESS].fd = -1;
+ pfds[DUMMY_PROCESS].events = 0;
+ pfds[DUMMY_PROCESS].revents = 0;
+
+ if ( !process_pool_disable &&
+ DIFF(last_dummy_exec_time, time(NULL)) > EXEC_DUMMY_EXPIRED)
+ {
+ __launchpad_exec_dummy(main_fd, pool_fd, -1);
+ }
+ }
+
+ if (poll(pfds, POLLFD_MAX, -1) < 0)
+ {
continue;
}
+ _D("pfds[LAUNCH_PAD].revents : 0x%x", pfds[LAUNCH_PAD].revents) ;
+ _D("pfds[POOL_SERVER].revents : 0x%x", pfds[POOL_SERVER].revents) ;
+ _D("pfds[DUMMY_PROCESS].revents : 0x%x", pfds[DUMMY_PROCESS].revents) ;
+
/* init with concerning X & EFL (because of booting
- * sequence problem)*/
- if (__launchpad_post_init() < 0) {
+ * sequence problem)*/
+ if (__launchpad_post_init() < 0)
+ {
_E("launcpad post init failed");
- exit(-1);
+ goto exit_main;
+ }
+
+ if ((pfds[LAUNCH_PAD].revents & POLLIN) != 0)
+ {
+ _D("pfds[LAUNCH_PAD].revents & POLLIN");
+ __launchpad_main_loop(pfds[LAUNCH_PAD].fd, pfds[POOL_SERVER].fd);
}
- for (i = 0; i < POLLFD_MAX; i++) {
- if ((pfds[i].revents & POLLIN) != 0) {
- __launchpad_main_loop(pfds[i].fd);
+ if ((pfds[POOL_SERVER].revents & POLLIN) != 0)
+ {
+ int server_fd, client_fd, client_pid;
+
+ server_fd = pfds[POOL_SERVER].fd;
+
+ _D("pfds[POOL_SERVER].revents & POLLIN");
+
+ if (dummy_process_pid == DUMMY_NONE)
+ {
+ __accept_dummy_process(server_fd, &client_fd, &client_pid);
+
+ dummy_process_pid = client_pid;
+ dummy_process_fd = client_fd;
+
+ pfds[DUMMY_PROCESS].fd = dummy_process_fd;
+ pfds[DUMMY_PROCESS].events = POLLIN|POLLHUP;
+ pfds[DUMMY_PROCESS].revents = 0;
+
+ _D("Dummy process was connected! (pid:%d)", dummy_process_pid);
+ }
+ else
+ {
+ __refuse_dummy_process(server_fd);
+
+ _E("Refused dummy process connection!");
}
}
+
+ if ((pfds[DUMMY_PROCESS].revents & (POLLHUP|POLLNVAL)) != 0)
+ {
+ _D("pfds[DUMMY_PROCESS].revents & (POLLHUP|POLLNVAL) (pid:%d)", dummy_process_pid);
+ close(pfds[DUMMY_PROCESS].fd);
+
+ dummy_process_pid = DUMMY_NONE;
+ dummy_process_fd = -1;
+
+ pfds[DUMMY_PROCESS].fd = -1;
+ pfds[DUMMY_PROCESS].events = 0;
+ pfds[DUMMY_PROCESS].revents = 0;
+ }
}
+
+ return 0;
+
+ exit_main:
+ if (main_fd != -1)
+ {
+ close(main_fd);
+ }
+
+ if (pool_fd != -1)
+ {
+ close(pool_fd);
+ }
+
+ return -1;
}
/usr/bin/wrt-client
-/usr/lib/wrt-wk2-bundles/libwrt-wk2-bundle.so
\ No newline at end of file
+/usr/lib/wrt-wk2-bundles/libwrt-wk2-bundle.so
+/usr/lib/wrt-plugins/w3c-widget-interface/libwrt-plugins-w3c-widget-interface.so
+/usr/lib/wrt-plugins/tizen-tizen/libwrt-plugins-tizen-tizen.so
{
int fd = -1;
struct sockaddr_un saddr;
- memset(&saddr, 0, sizeof(saddr));
int retry = 1;
int ret = -1;
+ memset(&saddr, 0x00, sizeof(struct sockaddr_un));
+
fd = socket(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0);
/* support above version 2.6.27*/
if (fd < 0) {
{
int len;
struct sockaddr_un aul_addr;
- memset(&aul_addr, 0, sizeof(aul_addr));
int sun_size;
app_pkt_t *pkt = NULL;
int cl = sizeof(struct ucred);
+ memset(&aul_addr, 0x00, sizeof(struct sockaddr_un));
sun_size = sizeof(struct sockaddr_un);
if ((*clifd = accept(fd, (struct sockaddr *)&aul_addr,
--- /dev/null
+/*
+ * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+/**
+ * @file process_pool.c
+ * @author Tae-Jeong Lee (taejeong.lee@samsung.com)
+ * @version 0.1
+ * @brief process pool socket apis
+ */
+
+#include <unistd.h>
+#include <sys/socket.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <linux/un.h>
+#include <errno.h>
+#include <stdio.h>
+
+#include "process_pool.h"
+#include "simple_util.h"
+
+#define TMP_PATH "/tmp"
+#define PROCESS_POOL_SERVER "wrt_process_pool_server"
+#define MAX_PENDING_CONNECTIONS 10
+#define CONNECT_RETRY_TIME 100 * 1000
+#define CONNECT_RETRY_COUNT 3
+
+int __create_process_pool_server()
+{
+ struct sockaddr_un addr;
+ int fd = -1;
+
+ memset(&addr, 0x00, sizeof(struct sockaddr_un));
+
+ fd = socket(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0);
+
+ if (fd < 0)
+ {
+ _E("socket error");
+ goto err_create_process_pool_server;
+ }
+
+ addr.sun_family = AF_UNIX;
+ snprintf(addr.sun_path, UNIX_PATH_MAX, "%s/%s", TMP_PATH, PROCESS_POOL_SERVER);
+ unlink(addr.sun_path);
+
+ _D("bind to %s", addr.sun_path);
+ if (bind(fd, (struct sockaddr *)&addr, sizeof(addr)) < 0)
+ {
+ _E("bind error");
+ goto err_create_process_pool_server;
+ }
+
+ _D("chmod to %s", addr.sun_path);
+ if (chmod(addr.sun_path, (S_IRWXU | S_IRWXG | S_IRWXO)) < 0)
+ {
+ _E("chmod error");
+ goto err_create_process_pool_server;
+ }
+
+ _D("listen to %s", addr.sun_path);
+ if (listen(fd, MAX_PENDING_CONNECTIONS) == -1)
+ {
+ _E("listen error");
+ goto err_create_process_pool_server;
+ }
+
+ _D("__create_process_pool_server done : %d", fd);
+ return fd;
+
+
+err_create_process_pool_server:
+
+ if (fd != -1)
+ {
+ close(fd);
+ }
+
+ return -1;
+}
+
+
+int __connect_process_pool_server()
+{
+ struct sockaddr_un addr;
+ int fd = -1;
+ int retry = CONNECT_RETRY_COUNT;
+ int send_ret = -1;
+ int client_pid = getpid();
+
+ memset(&addr, 0x00, sizeof(struct sockaddr_un));
+
+ fd = socket(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0);
+
+ if (fd < 0)
+ {
+ _E("socket error");
+
+ goto err_connect_process_pool_server;
+ }
+
+ addr.sun_family = AF_UNIX;
+ snprintf(addr.sun_path, UNIX_PATH_MAX, "%s/%s", TMP_PATH, PROCESS_POOL_SERVER);
+
+
+ _D("connect to %s", addr.sun_path);
+ while (connect(fd, (struct sockaddr *)&addr, sizeof(addr)) < 0)
+ {
+ if (errno != ETIMEDOUT || retry <= 0)
+ {
+ _E("connect error : %d", errno);
+
+ goto err_connect_process_pool_server;
+ }
+
+ usleep(CONNECT_RETRY_TIME);
+ retry--;
+ _D("re-connect to %s (%d)", addr.sun_path, retry);
+ }
+
+ send_ret = send(fd, &client_pid, sizeof(client_pid), 0);
+ _D("send(%d) : %d", client_pid, send_ret);
+
+ if (send_ret == -1)
+ {
+ _E("send error");
+
+ goto err_connect_process_pool_server;
+ }
+
+ _D("__connect_process_pool_server done : %d", fd);
+ return fd;
+
+err_connect_process_pool_server:
+
+ if (fd != -1)
+ {
+ close(fd);
+ }
+
+ return -1;
+}
+
+
+int __accept_dummy_process(int server_fd, int* out_client_fd, int* out_client_pid)
+{
+ int client_fd = -1, client_pid = 0, recv_ret = 0;
+
+ if (server_fd == -1 || out_client_fd == NULL || out_client_pid == NULL)
+ {
+ _E("arguments error!");
+
+ goto err__accept_dummy_process;
+ }
+
+ client_fd = accept(server_fd, NULL, NULL);
+
+ if (client_fd == -1)
+ {
+ _E("accept error!");
+
+ goto err__accept_dummy_process;
+ }
+
+ recv_ret = recv(client_fd, &client_pid, sizeof(client_pid), MSG_WAITALL);
+
+ if (recv_ret == -1)
+ {
+ _E("recv error!");
+
+ goto err__accept_dummy_process;
+ }
+
+ *out_client_fd = client_fd;
+ *out_client_pid = client_pid;
+
+ return *out_client_fd;
+
+err__accept_dummy_process:
+
+ if (client_fd != -1)
+ {
+ close(client_fd);
+ }
+
+ return -1;
+}
+
+void __refuse_dummy_process(int server_fd)
+{
+ int client_fd = -1;
+
+ if (server_fd == -1)
+ {
+ _E("arguments error!");
+
+ goto err__refuse_dummy_process;
+ }
+
+ client_fd = accept(server_fd, NULL, NULL);
+
+ if (client_fd == -1)
+ {
+ _E("accept error!");
+
+ goto err__refuse_dummy_process;
+ }
+
+ close(client_fd);
+ _D("refuse connection!");
+
+ return;
+
+err__refuse_dummy_process:
+
+ if (client_fd != -1)
+ {
+ close(client_fd);
+ }
+
+ return;
+}
+
+
+int __send_pkt_raw_data(int client_fd, app_pkt_t* pkt)
+{
+ int send_ret = 0;
+ int pkt_size = 0;
+
+ if (client_fd == -1 || pkt == NULL)
+ {
+ _E("arguments error!");
+
+ goto err__send_pkt_raw_data;
+ }
+
+ pkt_size = sizeof(pkt->cmd) + sizeof(pkt->len) + pkt->len;
+
+ send_ret = send(client_fd, pkt, pkt_size, 0);
+ _D("send(%d) : %d / %d", client_fd, send_ret, pkt_size);
+
+ if (send_ret == -1)
+ {
+ _E("send error!");
+
+ goto err__send_pkt_raw_data;
+ }
+ else if (send_ret != pkt_size)
+ {
+ _E("send byte fail!");
+
+ goto err__send_pkt_raw_data;
+ }
+
+ return 0;
+
+err__send_pkt_raw_data:
+
+ return -1;
+}
\ No newline at end of file
--- /dev/null
+# This env is enabled in private ONLY
+#export WRT_PROCESS_POOL_DISABLE=ON