Project

General

Profile

Wt + Apache + mod fcgid + Valgrind + gdb + SELinux - Deploy and Debug » History » Version 15

Wim Dumon, 01/15/2013 03:26 PM

1 1 Plug Gulp
h1. Deploy web application with (Wt + Apache + mod_fcgid) and Debug using (Valgrind + gdb) on Linux system with SELinux enforced.
2
3
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.
4
5 3 Plug Gulp
_+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!+_
6 1 Plug Gulp
7
These steps were tested with the following environment:
8
* Fedora 16 (3.3.1-5.fc16.x86_64)
9
* Wt 3.2.1 (from git)
10
* Apache 2.2.22
11
* mod_fcgid 2.3.6
12
* Valgrind 3.7.0
13
* gdb 7.3.50
14
15
+Steps to deploy and debug Wt application+
16
# Install Valgrind 3.7.0 or later (or Valgrind that supports in-built gdbserver).
17
# Install gdb.
18
# Install all the dependencies required by Wt:
19 9 Plug Gulp
<pre>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++</pre>
20 1 Plug Gulp
# Get Wt source code from git repo(http://www.webtoolkit.eu/git/wt.git) or download the source tarball from "Wt website":http://www.webtoolkit.eu/wt/download
21
# In file .../wt/src/fcgi/Server.C make following changes to the code in method Server::handleRequest:
22
** Set the boolean variable "debug" to true. This will enable debugging of dedicated-process.
23
** 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.
24
# Build debug version of Wt as follows (create a separate directory outside the Wt source directory and issue the following command in that directory):
25
<pre>cmake -DCMAKE_BUILD_TYPE=Debug -DCONNECTOR_FCGI=ON <<path to Wt source code directory>>
26
make
27
make install</pre>
28 4 Plug Gulp
# 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.
29 11 Plug Gulp
# 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 <pre>SET(CMAKE_MODULE_PATH <<incorrect directory path of the FindWt.cmake file>>)</pre> in your project's CMakeLists.txt file.
30 1 Plug Gulp
# In the FindWt.cmake file, make the following changes:
31
** Change the name of the variable Wt_FIND_COMPONENTS to Wt_FIND_COMPONENT_TYPE.
32
** 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):
33
<pre>
34
IF(CMAKE_BUILD_TYPE MATCHES Debug)
35
	SET( Wt_FIND_COMPONENT_TYPE Debug )
36
ELSEIF(CMAKE_BUILD_TYPE MATCHES Release)
37
	SET( Wt_FIND_COMPONENT_TYPE Release )
38
ELSE(CMAKE_BUILD_TYPE MATCHES Release)
39
	SET( Wt_FIND_COMPONENT_TYPE Release Debug )
40
ENDIF(CMAKE_BUILD_TYPE MATCHES Debug)
41
</pre>
42
** Change the following:
43
<pre>
44
IF(Wt_FIND_REQUIRED)
45
	MESSAGE(FATAL_ERROR "Could NOT find Wt")
46
ENDIF(Wt_FIND_REQUIRED)
47
</pre>
48
to:
49
<pre>
50
LIST(FIND Wt_FIND_COMPONENT_TYPE Release rv)
51
IF(NOT (rv EQUAL -1))
52
	MESSAGE(FATAL_ERROR "Could NOT find Wt")
53
ENDIF(NOT (rv EQUAL -1))
54
</pre>
55
** Similarly change the following:
56
<pre>
57
IF(Wt_FIND_REQUIRED_Debug)
58
	MESSAGE(FATAL_ERROR "Could NOT find Wt debug libraries")
59
ENDIF(Wt_FIND_REQUIRED_Debug)
60
</pre>
61
to:
62
<pre>
63
LIST(FIND Wt_FIND_COMPONENT_TYPE Debug rv)
64
IF(NOT (rv EQUAL -1))
65
	MESSAGE(FATAL_ERROR "Could NOT find Wt debug libraries")
66
ENDIF(NOT (rv EQUAL -1))
67
</pre>
68
** Delete the definitions of Wt_FIND_REQUIRED_Release and Wt_FIND_REQUIRED_Debug.
69
# 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):
70
<pre>
71
<IfModule mod_fcgid.c>
72
	NameVirtualHost *:80
73
	# [+] For debugging.
74
	FcgidMaxProcesses 1
75
	# [-] For debugging.
76
	<VirtualHost *:80>
77 13 Plug Gulp
        # Add this servername into the /etc/hosts file.
78 12 Plug Gulp
		ServerName www.testwtdbg.com
79 1 Plug Gulp
		ServerAlias testwtdbg.com
80
		DocumentRoot /var/www/testwtdbg/docroot
81
		AddHandler fcgid-script wt
82
		DirectoryIndex testwtdbg.wt
83
		<Directory /var/www/testwtdbg/docroot>
84
			Order Deny,Allow
85
			Allow from all
86
			Options +ExecCGI -Indexes
87
		</Directory>
88
		FcgidInitialEnv WT_APP_ROOT /var/www/testwtdbg/approot/
89
90
		# [+] For debugging.
91
		# Increase timeout of application process for debugging.
92
		FcgidIOTimeout 300
93
		FcgidConnectTimeout 300
94
		# Reduce the number of processes spawned to 1 so that it is easy for debugging.
95
		FcgidMaxProcessesPerClass 1
96
		FcgidMinProcessesPerClass 1
97
		# [-] For debugging.
98
	</VirtualHost>
99
</IfModule>
100
</pre>
101
# If required add the hostname(ServerName) specified in the wt.conf file to the /etc/hosts file.
102
# 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).
103
# Build a test Wt application as follows:
104
** Create a project directory.
105 11 Plug Gulp
** Create the cmake build file CMakeLists.txt in the project directory and enter the following in that file:
106 1 Plug Gulp
<pre>
107
cmake_minimum_required(VERSION 2.8)
108
109
project(testwtdbg)
110
111
set(P_TARGET_NAME testwtdbg.wt)
112
# set(CMAKE_MODULE_PATH <<directory path of the FindWt.cmake file>>)
113
114
set(CMAKE_BUILD_TYPE Debug)
115
116
find_package(Wt REQUIRED)
117
118
if(CMAKE_BUILD_TYPE MATCHES Debug)
119
	if(Wt_DEBUG_FOUND)
120
		message(STATUS "Building debug mode ${P_TARGET_NAME}")
121
		set(P_FCGI_LIB ${Wt_FCGI_DEBUG_LIBRARY})
122
		set(P_WT_LIB ${Wt_DEBUG_LIBRARY})
123
	else(Wt_DEBUG_FOUND)
124 7 Plug Gulp
		message(FATAL_ERROR "Failed to find debug mode Wt for building debug mode ${P_TARGET_NAME}")
125 1 Plug Gulp
	endif(Wt_DEBUG_FOUND)
126
else(CMAKE_BUILD_TYPE MATCHES Debug)
127
	if(Wt_FOUND)
128
		message(STATUS "Building non-debug mode ${P_TARGET_NAME}")
129
		set(P_FCGI_LIB ${Wt_FCGI_LIBRARY})
130
		set(P_WT_LIB ${Wt_LIBRARY})
131
	else(Wt_FOUND)
132 7 Plug Gulp
		message(FATAL_ERROR "Failed to find non-debug mode Wt for building non-debug mode ${P_TARGET_NAME}")
133 1 Plug Gulp
	endif(Wt_FOUND)
134
endif(CMAKE_BUILD_TYPE MATCHES Debug)
135
136
include_directories(${Wt_INCLUDE_DIR})
137
add_executable(${P_TARGET_NAME} main.cpp)
138
target_link_libraries(${P_TARGET_NAME} ${P_FCGI_LIB} ${P_WT_LIB})
139
</pre>
140
** Create the source file, main.cpp, in the project directory and enter the following code:
141
<pre><code class="cpp">
142
#include <Wt/WApplication>
143
#include <Wt/WContainerWidget>
144
#include <Wt/WVBoxLayout>
145
#include <Wt/WHBoxLayout>
146
#include <Wt/WText>
147
148
using namespace Wt;
149
150
class DispAppDoc: public WApplication
151
{
152
	public:
153
		DispAppDoc(const Wt::WEnvironment& env);
154
};
155
156
DispAppDoc::DispAppDoc(const Wt::WEnvironment& env)
157
    : Wt::WApplication(env)
158
{
159
	WVBoxLayout *pVBoxLayout = new WVBoxLayout();
160
161
	WHBoxLayout *pHBoxLayout = new WHBoxLayout();
162
	pHBoxLayout->addWidget(new WText("appRoot(): "));
163
	pHBoxLayout->addWidget(new WText(appRoot()));
164
	pVBoxLayout->addLayout(pHBoxLayout, 0, AlignTop | AlignLeft);
165
166
	pHBoxLayout = new WHBoxLayout();
167
	pHBoxLayout->addWidget(new WText("docRoot(): "));
168
	pHBoxLayout->addWidget(new WText(docRoot()));
169
	pVBoxLayout->addLayout(pHBoxLayout, 0, AlignTop | AlignLeft);
170
171
	root()->setLayout(pVBoxLayout, AlignTop | AlignJustify);
172
}
173
174
WApplication* createApplication(const Wt::WEnvironment& env) 
175
{
176
    return new DispAppDoc(env);
177
}
178
179
int main(int argc, char *argv[])
180
{
181
    return Wt::WRun(argc, argv, &createApplication);
182
}
183
</code></pre>
184
** Build the code by issuing the "cmake ." command from under the project directory.
185
** Copy the Wt application binary from the project directory to the the webhost's docroot.
186
# Create a directory /var/run/wt and change it's permission to rwxr-----
187
# Change the owner and group of /var/run/wt to apache.
188
# To see what SELinux errors will occur, run the Wt application with SELinux mode set to permissive by executing the command: setenforce 0
189
# 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.
190
** Change the selinux attributes of /var/run/wt to httpd_sys_content_t (or httpd_sys_content_rw_t) as follows:
191
<pre>semanage fcontext -a -t httpd_sys_rw_content_t /var/run/wt
192
restorecon -r -v /var/run/wt</pre>
193
** Enable that all files labeled as httpd context can be read/write/execute as follows (note that this is not the right solution):
194
<pre>setsebool -P httpd_unified 1</pre>
195
** Enable the Wt application to connect to network as follows:
196
<pre>setsebool -P httpd_can_network_connect 1</pre>
197 5 Plug Gulp
# To make the Wt application work with Valgrind, update the /etc/wt/wt_config.xml file as follows:
198
** Either choose <dedicated-process> or <shared-process>. If <shared-process> is selected then set the <number-processes> to 1.
199
** Set <timeout> to -1.
200
** Add the value of <valgrind-path> 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.):
201
<pre><vlagrind-path><<full valgrind path>> --trace-children=yes --vgdb=full --vgdb-error=0</valgrind-path></pre>
202
** Set <debug> to stack.
203 1 Plug Gulp
# To connect to Valgrind launched by Wt, do the following:
204
** Make a copy of <<vgdb path>>/vgdb to <<vgdb path>>/vgdb_wt
205
** Change owner and group of vgdb_wt to apache
206
** Set uid and gid of vgdb_wt as follows: chmod ug+s <<vgdb path>>/vgdb_wt
207
** Watch the webserver log messages using the command: tail -f /var/log/httpd/error_log
208
** Start the webserver.
209
** Start the webbrowser.
210
** Pass debug as the last parameter of the URL to access the Wt application to be debugged e.g. http://www.testwtdbg.com?debug
211
** From the webserver log note the PID of the Wt application that valgrind launches. This PID is passed as parameter to vgdb.
212
** 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 "???"
213 7 Plug Gulp
** Run gdb with the Wt application as parameter. On the gdb prompt issue the commands
214 1 Plug Gulp
<pre>set remotetimeout 999999</pre> Required only if there is error such as "unrecognized item "timeout" in "qSupported" response" when the vgdb connects to valgrind.
215
<pre>target remote | vgdb_wt --max-invoke-ms=0 --pid=<<the pid of the Wt application to debug>></pre>--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.</pre>
216 8 Plug Gulp
** Now debug the running Wt application as you would with the normal desktop/embedded application i.e. set breakpoint, view backtrace, stepwise debug etc.
217 7 Plug Gulp
218
_+Please update the document if you find any mistakes or it has become outdated, or let me know at "Plug Gulp":mailto:plug.gulp@gmail.com and I will update it.+_
219
220
Happy (de)bugging!
221
222
Thanks and regards,
223
224
~Plug