Project

General

Profile

Actions

Deploy web application with (Wt + Apache + mod_fcgid) and Debug using (Valgrind + gdb) on Linux system with SELinux enforced.

This section describes the steps required to deploy Wt application under Apache with mod_fcgid module. The steps also describe configuring the system so that Wt application work with SELinux. Finally this section describes the setup to enable debugging the deployed Wt application using Valgrind and gdb.

Please note that this setup is for development and debug environment only. Please do not use these steps as-is under production environment. You are warned!

These steps were tested with the following environment:

  • Fedora 16 (3.3.1-5.fc16.x86_64)
  • Wt 3.2.1 (from git)
  • Apache 2.2.22
  • mod_fcgid 2.3.6
  • Valgrind 3.7.0
  • gdb 7.3.50

Steps to deploy and debug Wt application

  1. Install Valgrind 3.7.0 or later (or Valgrind that supports in-built gdbserver).
  2. Install gdb.
  3. Install all the dependencies required by Wt: Boost-devel, pango-devel, GraphicsMagick-devel, libharu-devel, postgreSQL-devel, firebird-devel, OpenSSL-devel, zlib-devel, Qt-devel, fastcgi-devel, httpd, mod_fcgid, doxygen, cmake, gcc, g++, glibc, libstd++
  4. Get Wt source code from git repo(http://www.webtoolkit.eu/git/wt.git) or download the source tarball from Wt website
  5. In file .../wt/src/fcgi/Server.C make following changes to the code in method Server::handleRequest:
    • Set the boolean variable "debug" to true. This will enable debugging of dedicated-process.
    • Increase the maxTries parameter value passed during connectToSession method invocation to 3000 or more. This will reduce the number of session timeouts experienced by Wt application.
  6. Build debug version of Wt as follows (create a separate directory outside the Wt source directory and issue the following command in that directory): cmake -DCMAKE_BUILD_TYPE=Debug -DCONNECTOR_FCGI=ON <> make make install
  7. Usually Wt libraries are installed under /usr/local/lib. On some systems this path might not be in the library search path. Hence the Wt application launch will fail. To remedy this situation, please create symbolic links under /usr/lib (or under /usr/lib64 for 64-bit OS) to the Wt libraries.
  8. The Wt cmake module file, FindWt.cmake, should be installed under the directory where all the cmake modules are installed e.g. under /usr/share/cmake/Modules/. But Wt installation sometimes wrongly installs it under /usr/local/usr/share/cmake/Modules/. If that is the case then copy the FindWt.cmake file to the correct place or use the

<!-- -->

SET(CMAKE_MODULE_PATH <<incorrect directory path of the FindWt.cmake file>>)

in your project's CMakeLists.txt file.

# In the FindWt.cmake file, make the following changes:

Change the name of the variable Wt_FIND_COMPONENTS to Wt_FIND_COMPONENT_TYPE.

Depending upon the type of Wt application being built i.e. Release or Debug, set the value of Wt_FIND_COMPONENT_TYPE (note that this code does not take into consideration other build types. You can expand this as required):

IF(CMAKE_BUILD_TYPE MATCHES Debug)
    SET( Wt_FIND_COMPONENT_TYPE Debug )
ELSEIF(CMAKE_BUILD_TYPE MATCHES Release)
    SET( Wt_FIND_COMPONENT_TYPE Release )
ELSE(CMAKE_BUILD_TYPE MATCHES Release)
    SET( Wt_FIND_COMPONENT_TYPE Release Debug )
ENDIF(CMAKE_BUILD_TYPE MATCHES Debug)

Change the following:

IF(Wt_FIND_REQUIRED)
    MESSAGE(FATAL_ERROR "Could NOT find Wt")
ENDIF(Wt_FIND_REQUIRED)

to:

LIST(FIND Wt_FIND_COMPONENT_TYPE Release rv)
IF(NOT (rv EQUAL -1))
    MESSAGE(FATAL_ERROR "Could NOT find Wt")
ENDIF(NOT (rv EQUAL -1))

Similarly change the following:

IF(Wt_FIND_REQUIRED_Debug)
    MESSAGE(FATAL_ERROR "Could NOT find Wt debug libraries")
ENDIF(Wt_FIND_REQUIRED_Debug)

to:

LIST(FIND Wt_FIND_COMPONENT_TYPE Debug rv)
IF(NOT (rv EQUAL -1))
    MESSAGE(FATAL_ERROR "Could NOT find Wt debug libraries")
ENDIF(NOT (rv EQUAL -1))

Delete the definitions of Wt_FIND_REQUIRED_Release and Wt_FIND_REQUIRED_Debug.

# Create /etc/httpd/conf.d/wt.conf file for Wt related configuration of httpd. Enter the following in the wt.conf file (Note that your configuration file may differ, but the important things to note are the statements in the file marked within the "For debugging" comment block):

<IfModule mod_fcgid.c>
    NameVirtualHost *:80
    # [+] For debugging.
    FcgidMaxProcesses 1
    # [-] For debugging.
    <VirtualHost *:80>
        # Add this servername into the /etc/hosts file.
        ServerName www.testwtdbg.com
        ServerAlias testwtdbg.com
        DocumentRoot /var/www/testwtdbg/docroot
        AddHandler fcgid-script wt
        DirectoryIndex testwtdbg.wt
        <Directory /var/www/testwtdbg/docroot>
            Order Deny,Allow
            Allow from all
            Options +ExecCGI -Indexes
        </Directory>
        FcgidInitialEnv WT_APP_ROOT /var/www/testwtdbg/approot/

        # [+] For debugging.
        # Increase timeout of application process for debugging.
        FcgidIOTimeout 300
        FcgidConnectTimeout 300
        # Reduce the number of processes spawned to 1 so that it is easy for debugging.
        FcgidMaxProcessesPerClass 1
        FcgidMinProcessesPerClass 1
        # [-] For debugging.
    </VirtualHost>
</IfModule>

# If required add the hostname(ServerName) specified in the wt.conf file to the /etc/hosts file.

# Copy the Wt default resources directory, available under Wt library source directory, to the webhost's docroot (refer the wt.conf file for docroot path).

# Build a test Wt application as follows:

Create a project directory.

Create the cmake build file CMakeLists.txt in the project directory and enter the following in that file:

cmake_minimum_required(VERSION 2.8)

project(testwtdbg)

set(P_TARGET_NAME testwtdbg.wt)
# set(CMAKE_MODULE_PATH <<directory path of the FindWt.cmake file>>)

set(CMAKE_BUILD_TYPE Debug)

find_package(Wt REQUIRED)

if(CMAKE_BUILD_TYPE MATCHES Debug)
    if(Wt_DEBUG_FOUND)
        message(STATUS "Building debug mode ${P_TARGET_NAME}")
        set(P_FCGI_LIB ${Wt_FCGI_DEBUG_LIBRARY})
        set(P_WT_LIB ${Wt_DEBUG_LIBRARY})
    else(Wt_DEBUG_FOUND)
        message(FATAL_ERROR "Failed to find debug mode Wt for building debug mode ${P_TARGET_NAME}")
    endif(Wt_DEBUG_FOUND)
else(CMAKE_BUILD_TYPE MATCHES Debug)
    if(Wt_FOUND)
        message(STATUS "Building non-debug mode ${P_TARGET_NAME}")
        set(P_FCGI_LIB ${Wt_FCGI_LIBRARY})
        set(P_WT_LIB ${Wt_LIBRARY})
    else(Wt_FOUND)
        message(FATAL_ERROR "Failed to find non-debug mode Wt for building non-debug mode ${P_TARGET_NAME}")
    endif(Wt_FOUND)
endif(CMAKE_BUILD_TYPE MATCHES Debug)

include_directories(${Wt_INCLUDE_DIR})
add_executable(${P_TARGET_NAME} main.cpp)
target_link_libraries(${P_TARGET_NAME} ${P_FCGI_LIB} ${P_WT_LIB})

Create the source file, main.cpp, in the project directory and enter the following code:

#include <Wt/WApplication>
#include <Wt/WContainerWidget>
#include <Wt/WVBoxLayout>
#include <Wt/WHBoxLayout>
#include <Wt/WText>

using namespace Wt;

class DispAppDoc: public WApplication
{
    public:
        DispAppDoc(const Wt::WEnvironment& env);
};

DispAppDoc::DispAppDoc(const Wt::WEnvironment& env)
    : Wt::WApplication(env)
{
    WVBoxLayout *pVBoxLayout = new WVBoxLayout();

    WHBoxLayout *pHBoxLayout = new WHBoxLayout();
    pHBoxLayout->addWidget(new WText("appRoot(): "));
    pHBoxLayout->addWidget(new WText(appRoot()));
    pVBoxLayout->addLayout(pHBoxLayout, 0, AlignTop | AlignLeft);

    pHBoxLayout = new WHBoxLayout();
    pHBoxLayout->addWidget(new WText("docRoot(): "));
    pHBoxLayout->addWidget(new WText(docRoot()));
    pVBoxLayout->addLayout(pHBoxLayout, 0, AlignTop | AlignLeft);

    root()->setLayout(pVBoxLayout, AlignTop | AlignJustify);
}

WApplication* createApplication(const Wt::WEnvironment& env) 
{
    return new DispAppDoc(env);
}

int main(int argc, char *argv[])
{
    return Wt::WRun(argc, argv, &createApplication);
}

Build the code by issuing the "cmake ." command from under the project directory.

Copy the Wt application binary from the project directory to the the webhost's docroot.

# Create a directory /var/run/wt and change it's permission to rwxr-------

# Change the owner and group of /var/run/wt to apache.

# To see what SELinux errors will occur, run the Wt application with SELinux mode set to permissive by executing the command: setenforce 0

# Once the information on SELinux errors related to webserver and application is available, make changes to SELinux policy as suggested in the SELinux-troubleshooter. Set the SELinux mode back to enforcing by issuing the command: setenforce 1. Atleast following three changes are required to successfully launch Wt application from a webbrowser.

Change the selinux attributes of /var/run/wt to httpd_sys_content_t (or httpd_sys_content_rw_t) as follows:

semanage fcontext -a -t httpd_sys_rw_content_t /var/run/wt
restorecon -r -v /var/run/wt

Enable that all files labeled as httpd context can be read/write/execute as follows (note that this is not the right solution):

setsebool -P httpd_unified 1

Enable the Wt application to connect to network as follows:

setsebool -P httpd_can_network_connect 1

# To make the Wt application work with Valgrind, update the /etc/wt/wt_config.xml file as follows:

Either choose or . If is selected then set the to 1.

Set to --1.

Add the value of as follows (pass low value to the valgrind parameter ---vgdb-poll only if debugger becomes slow. This is required only when ---max-invoke-ms=0 is passed to vgdb. Refer to Valgrind manual for details on why this is required.):

<vlagrind-path><<full valgrind path>> --trace-children=yes --vgdb=full --vgdb-error=0</valgrind-path>

Set to stack.

# To connect to Valgrind launched by Wt, do the following:

Make a copy of <>/vgdb to <>/vgdb_wt

Change owner and group of vgdb_wt to apache

Set uid and gid of vgdb_wt as follows: chmod ug+s <>/vgdb_wt

Watch the webserver log messages using the command: tail -f /var/log/httpd/error_log

Start the webserver.

Start the webbrowser.

Pass debug as the last parameter of the URL to access the Wt application to be debugged e.g. http://www.testwtdbg.com?debug

From the webserver log note the PID of the Wt application that valgrind launches. This PID is passed as parameter to vgdb.

Check the valgrind FIFO names under /tmp directory. The FIFO names usually take the form of vgdb-pipe-[to/from/shared-mem]vgdb[from/to/]-PID-by-USER-on-HOSTNAME. If USER and HOSTNAME do not match the user name and host name from where gdb/vgdb_wt was launched, then set environment variables LOGNAME and HOST to the value of USER and HOSTNAME as used in the FIFO names respectively. e.g. if the USER is "???" and also the HOSTNAME is "?", then set the environment variable LOGNAME to "?" and the environment variable HOST to "???"

Run gdb with the Wt application as parameter. On the gdb prompt issue the commands

set remotetimeout 999999

Required only if there is error such as "unrecognized item "timeout\" in "qSupported" response\" when the vgdb connects to valgrind.

target remote | vgdb_wt --max-invoke-ms=0 --pid=<<the pid of the Wt application to debug>>

---max-invoke-ms=0 is required only when ptrace calls within valgrind refuse to execute due to permission/process-ownership mismatch issues between valgrind run process and vgdb.

Now debug the running Wt application as you would with the normal desktop/embedded application i.e. set breakpoint, view backtrace, stepwise debug etc.

Please update the document if you find any mistakes or it has become outdated, or let me know at Plug Gulp and I will update it.

Happy (de)bugging!

Thanks and regards,

~Plug

Updated by Wim Dumon almost 8 years ago ยท 15 revisions