Project

General

Profile

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

Plug Gulp, 04/17/2012 08:05 AM

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
_+Please note that this setup is for development and debug environment only. Please do not use these steps as it is under production environment. You are warned!+_
6
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
<pre>Boost-devel, pango-devel, ImageMagick-devel, libharu-devel, postgreSQL-devel, firebird-devel, OpenSSL-devel, zlib-devel, Qt-devel, fastcgi-devel, mod_fcgid, doxygen, cmake, gcc, g++, glibc, libstd++</pre>
20
# 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
# Usually Wt libraries are installed under /usr/local/lib. On some system 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 2 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 installes 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 CMakeList.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
		ServerName www.testwtdbg.com # Add this hostname into the /etc/hosts file.
78
		ServerAlias testwtdbg.com
79
		DocumentRoot /var/www/testwtdbg/docroot
80
		AddHandler fcgid-script wt
81
		DirectoryIndex testwtdbg.wt
82
		<Directory /var/www/testwtdbg/docroot>
83
			Order Deny,Allow
84
			Allow from all
85
			Options +ExecCGI -Indexes
86
		</Directory>
87
		FcgidInitialEnv WT_APP_ROOT /var/www/testwtdbg/approot/
88
89
		# [+] For debugging.
90
		# Increase timeout of application process for debugging.
91
		FcgidIOTimeout 300
92
		FcgidConnectTimeout 300
93
		# Reduce the number of processes spawned to 1 so that it is easy for debugging.
94
		FcgidMaxProcessesPerClass 1
95
		FcgidMinProcessesPerClass 1
96
		# [-] For debugging.
97
	</VirtualHost>
98
</IfModule>
99
</pre>
100
# If required add the hostname(ServerName) specified in the wt.conf file to the /etc/hosts file.
101
# 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).
102
# Build a test Wt application as follows:
103
** Create a project directory.
104
** Create the cmake build file CMakeList.txt in the project directory and enter the following in that file:
105
<pre>
106
cmake_minimum_required(VERSION 2.8)
107
108
project(testwtdbg)
109
110
set(P_TARGET_NAME testwtdbg.wt)
111
# set(CMAKE_MODULE_PATH <<directory path of the FindWt.cmake file>>)
112
113
set(CMAKE_BUILD_TYPE Debug)
114
115
find_package(Wt REQUIRED)
116
117
if(CMAKE_BUILD_TYPE MATCHES Debug)
118
	if(Wt_DEBUG_FOUND)
119
		message(STATUS "Building debug mode ${P_TARGET_NAME}")
120
		set(P_FCGI_LIB ${Wt_FCGI_DEBUG_LIBRARY})
121
		set(P_WT_LIB ${Wt_DEBUG_LIBRARY})
122
	else(Wt_DEBUG_FOUND)
123
		message(STATUS "Failed to find debug mode Wt for building debug mode ${P_TARGET_NAME}")
124
		return()
125
	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
		message(STATUS "Failed to find non-debug mode Wt for building non-debug mode ${P_TARGET_NAME}")
133
		return()
134
	endif(Wt_FOUND)
135
endif(CMAKE_BUILD_TYPE MATCHES Debug)
136
137
include_directories(${Wt_INCLUDE_DIR})
138
add_executable(${P_TARGET_NAME} main.cpp)
139
target_link_libraries(${P_TARGET_NAME} ${P_FCGI_LIB} ${P_WT_LIB})
140
</pre>
141
** Create the source file, main.cpp, in the project directory and enter the following code:
142
<pre><code class="cpp">
143
#include <Wt/WApplication>
144
#include <Wt/WContainerWidget>
145
#include <Wt/WVBoxLayout>
146
#include <Wt/WHBoxLayout>
147
#include <Wt/WText>
148
149
using namespace Wt;
150
151
class DispAppDoc: public WApplication
152
{
153
	public:
154
		DispAppDoc(const Wt::WEnvironment& env);
155
};
156
157
DispAppDoc::DispAppDoc(const Wt::WEnvironment& env)
158
    : Wt::WApplication(env)
159
{
160
	WVBoxLayout *pVBoxLayout = new WVBoxLayout();
161
162
	WHBoxLayout *pHBoxLayout = new WHBoxLayout();
163
	pHBoxLayout->addWidget(new WText("appRoot(): "));
164
	pHBoxLayout->addWidget(new WText(appRoot()));
165
	pVBoxLayout->addLayout(pHBoxLayout, 0, AlignTop | AlignLeft);
166
167
	pHBoxLayout = new WHBoxLayout();
168
	pHBoxLayout->addWidget(new WText("docRoot(): "));
169
	pHBoxLayout->addWidget(new WText(docRoot()));
170
	pVBoxLayout->addLayout(pHBoxLayout, 0, AlignTop | AlignLeft);
171
172
	root()->setLayout(pVBoxLayout, AlignTop | AlignJustify);
173
}
174
175
WApplication* createApplication(const Wt::WEnvironment& env) 
176
{
177
    return new DispAppDoc(env);
178
}
179
180
int main(int argc, char *argv[])
181
{
182
    return Wt::WRun(argc, argv, &createApplication);
183
}
184
</code></pre>
185
** Build the code by issuing the "cmake ." command from under the project directory.
186
** Copy the Wt application binary from the project directory to the the webhost's docroot.
187
# Create a directory /var/run/wt and change it's permission to rwxr-----
188
# Change the owner and group of /var/run/wt to apache.
189
# To make the Wt application work with Valgrind, update the /etc/wt/wt_config.xml file as follows:
190
** Either choose <dedicated-process> or <shared-process>. If <shared-process> is selected then set the <number-processes> to 1.
191
** Set <timeout> to -1.
192
** 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.):
193
<pre><vlagrind-path><<full valgrind path>> --trace-children=yes --vgdb=full --vgdb-error=0</valgrind-path></pre>
194
** Set <debug> to stack.
195
# To see what SELinux errors will occur, run the Wt application with SELinux mode set to permissive by executing the command: setenforce 0
196
# 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.
197
** Change the selinux attributes of /var/run/wt to httpd_sys_content_t (or httpd_sys_content_rw_t) as follows:
198
<pre>semanage fcontext -a -t httpd_sys_rw_content_t /var/run/wt
199
restorecon -r -v /var/run/wt</pre>
200
** Enable that all files labeled as httpd context can be read/write/execute as follows (note that this is not the right solution):
201
<pre>setsebool -P httpd_unified 1</pre>
202
** Enable the Wt application to connect to network as follows:
203
<pre>setsebool -P httpd_can_network_connect 1</pre>
204
# To connect to Valgrind launched by Wt, do the following:
205
** Make a copy of <<vgdb path>>/vgdb to <<vgdb path>>/vgdb_wt
206
** Change owner and group of vgdb_wt to apache
207
** Set uid and gid of vgdb_wt as follows: chmod ug+s <<vgdb path>>/vgdb_wt
208
** Watch the webserver log messages using the command: tail -f /var/log/httpd/error_log
209
** Start the webserver.
210
** Start the webbrowser.
211
** Pass debug as the last parameter of the URL to access the Wt application to be debugged e.g. http://www.testwtdbg.com?debug
212
** From the webserver log note the PID of the Wt application that valgrind launches. This PID is passed as parameter to vgdb.
213
** 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 ???
214
** Run gdb with the Wt application as parameter. On the gdb prompt issue to command
215
<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.
216
<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>