1
#! /bin/sh /usr/share/dpatch/dpatch-run
2
## dont-loose-data-on-shutdown.dpatch by <alain@debian.org>
4
## All lines beginning with `## DP:' are a description of the patch.
5
## DP: Wait for all threads to first submit their data to the database.
6
## DP: This fixes potentially inconsistent data.
9
diff -urNad steam-2.2.31~/loader.pike steam-2.2.31/loader.pike
10
--- steam-2.2.31~/loader.pike 2006-09-24 17:50:47.000000000 +0200
11
+++ steam-2.2.31/loader.pike 2006-11-21 15:59:14.000000000 +0100
18
static int restart = 0;
20
static int keep_services_running = 1;
23
+array get_pids_from_pidfile () {
24
+ if ( !stringp(pidfile) ) return 0;
26
+ string pid_content = Stdio.read_file( pidfile );
27
+ if ( !stringp(pid_content) || sizeof(pid_content) < 1 ) return 0;
28
+ array pids = replace( pid_content, "\n", " " ) / " ";
29
+ for ( int i=0; i<sizeof(pids); i++ ) pids[i] = (int)(pids[i]);
30
+ // make sure the loader PID is always the first one in the array:
31
+ pids -= ({ loaderPID, serverPID });
32
+ pids = ({ loaderPID, serverPID }) + pids;
37
+ werror( "Error while trying to read pidfile %s :\n%O\n", pidfile, err );
41
+int write_pids_to_pidfile ( array pids ) {
42
+ if ( !arrayp(pids) ) return 0;
43
+ array new_pids = pids - ({ loaderPID, serverPID, 0 });
44
+ if ( serverPID != 0 ) new_pids = ({ serverPID }) + new_pids;
45
+ for ( int i=0; i<sizeof(new_pids); i++ ) new_pids[i] = (string)(new_pids[i]);
47
+ Stdio.write_file( pidfile, (string)loaderPID + "\n" + (new_pids * " ") );
51
+ werror( "Error while trying to write pidfile %s :\n%O\n", pidfile, err );
55
+int add_pid_to_pidfile ( int pid ) {
56
+ if ( pid == 0 ) return 0;
57
+ array pids = get_pids_from_pidfile();
58
+ if ( !arrayp(pids) ) return 0;
59
+ if ( search( pids, pid ) < 0 ) pids += ({ pid });
60
+ return write_pids_to_pidfile( pids );
64
+int remove_pid_from_pidfile ( int pid ) {
65
+ if ( pid == 0 || pid == loaderPID ) return 0;
66
+ array pids = get_pids_from_pidfile();
67
+ if ( !arrayp(pids) ) return 0;
68
+ return write_pids_to_pidfile( pids - ({ pid }) );
72
object start_service(string service, string ticket)
74
array loader_args = ({ });
77
if ( stringp(server_ip) ) runArr += ({ "--host="+server_ip });
79
- serviceLog->write( "Starting service \"%s\" ...\n", service );
80
+ serviceLog->write( "Starting service \"%s\" ...\nTime: %s",
81
+ service, ctime(time()) );
82
if ( sizeof( loader_args ) > 0 )
83
serviceLog->write( "Loader arguments: %O\n", loader_args );
84
mServiceLogs[service] = serviceLog;
87
kill( pid, signum("SIGKILL") );
89
- // remove old pid from pid_file:
91
- if ( pid != 0 ) err = catch {
92
- string pid_content = Stdio.read_file( pidfile );
93
- if ( stringp(pid_content) && sizeof(pid_content)>0 ) {
94
- pid_content = replace( pid_content, "\n", " " );
95
- array pids = pid_content / " ";
96
- for ( int i=sizeof(pids)-1; i>=0; i-- ) {
97
- if ( (int)(pids[i]) == pid ) pids -= ({ pids[i] });
98
- else if ( pids[i] == "" ) pids -= ({ pids[i] }); // cosmetics
100
- pid_content = pids * " ";
101
- int index = search( pid_content, " " );
102
- if ( index >= 0 ) pid_content[index] = '\n'; // newline after loader PID
103
- Stdio.write_file( pidfile, pid_content );
106
+ if ( remove_pid_from_pidfile( pid ) )
107
mServicePIDs[service] = 0;
110
- werror( "Error while removing service \"%s\" PID from pidfile: %O\n", service, err );
112
+ werror( "Could not remove service \"%s\" PID %d from pidfile\n",
117
void stop_services ()
119
mServiceLogs[service]->write("PID: %d\n",
120
mServices[service]->pid());
121
mServicePIDs[service] = mServices[service]->pid();
122
- Stdio.append_file(pidfile, " " + mServices[service]->pid());
123
+ if ( !add_pid_to_pidfile( mServices[service]->pid() ) )
124
+ werror( "Could not add service \"%s\" PID %d to pidfile.\n",
125
+ service, mServices[service]->pid() );
129
@@ -234,12 +274,19 @@
130
write("LogDir: "+logdir+"\n");
131
write("Params: "+sprintf("%O", params[1..])+"\n");
133
- ret = Process.create_process( runArr,
134
+ object server_process = Process.create_process( runArr,
135
([ "env": cenv + env,
141
+ serverPID = server_process->pid();
142
+ if ( serverPID != 0 && !add_pid_to_pidfile( serverPID ) )
143
+ werror( "Could not add server PID %d to pidfile %s !\n", serverPID,
145
+ ret = server_process->wait();
146
+ remove_pid_from_pidfile( serverPID );
148
write("Returned: "+ ret+"\n");
151
@@ -284,15 +331,17 @@
154
werror("Server killed !\n");
155
- object f = Stdio.File(pidfile,"r");
156
- string pid = f->read();
158
- array pids = pid / " ";
159
- foreach ( pids, string p ) {
160
- if ( !stringp(p) || sizeof(p)<1 ) continue;
161
- if ( (int)p != getpid() ) {
162
- werror("Killing: " + p + "\n");
163
- kill((int)p, signum("SIGQUIT"));
164
+ array pids = get_pids_from_pidfile();
165
+ if ( !arrayp(pids) ) {
166
+ werror( "Could not open pidfile, only killing server (pid %d)\n",
168
+ kill( serverPID, signum("SIGQUIT") );
171
+ foreach ( pids, int pid ) {
172
+ if ( pid != getpid() ) {
173
+ werror( "Killing: %d\n", pid );
174
+ kill( pid, signum("SIGQUIT") );
180
main(int argc, array(string) argv)
182
- int pid = getpid();
183
+ loaderPID = getpid();
185
signal(signum("QUIT"), got_kill);
186
signal(signum("TERM"), got_kill);
191
- Stdio.File f = Stdio.File( pidfile, "cwt" );
192
- f->write((string)pid);
195
+ if ( !write_pids_to_pidfile( ({ loaderPID }) ) )
196
+ werror( "Could not add loader PID %d to pidfile %s !\n", loaderPID,
198
thread_create(run, argv);
201
diff -urNad steam-2.2.31~/server/database.pike steam-2.2.31/server/database.pike
202
--- steam-2.2.31~/server/database.pike 2006-10-09 21:17:47.000000000 +0200
203
+++ steam-2.2.31/server/database.pike 2006-11-21 15:59:14.000000000 +0100
206
private static int CONVERSION = 0;
208
+private static int log_save_queue_modulo = 0;
210
private static mapping(string:int) mSaveRequests = ([ ]);
212
string generate_request_name(int oid, mixed ident, mixed index)
217
+ * Set logging of the save queue size. If bigger than 0, then the save daemon
218
+ * will output the size of the save queue every "modulo" elements. You can
219
+ * switch this off again by setting this value to 0.
221
+ * @param modulo the save daemon will output the save queue size whenever it
222
+ * is a multiple of this value
223
+ * @return the previously set modulo
225
+int log_save_queue ( int modulo )
227
+ int tmp = log_save_queue_modulo;
228
+ log_save_queue_modulo = modulo;
233
* demon function to store pending object saves to the database.
234
* This function is started as a thread and waits for objects entering
235
* a queue to save them to the database.
240
- if (oSaveQueue->size() == 0) {
242
+ int save_size = oSaveQueue->size();
243
+ if (save_size == 0) {
246
+ else if ( (log_save_queue_modulo > 0) &&
247
+ (save_size % log_save_queue_modulo == 0) ) {
248
+ MESSAGE( "database: %d items left to save...", save_size );
249
+ werror( "database: %d items left to save...\n", save_size );
253
FATAL("/**************** database_save_demon *************/\n"+
254
diff -urNad steam-2.2.31~/server/server.pike steam-2.2.31/server/server.pike
255
--- steam-2.2.31~/server/server.pike 2006-10-11 23:39:40.000000000 +0200
256
+++ steam-2.2.31/server/server.pike 2006-11-21 15:59:14.000000000 +0100
257
@@ -624,14 +624,28 @@
259
static private void got_kill(int sig)
261
- MESSAGE("Shutting down !\n");
262
+ MESSAGE( "Shutting down ! (waiting for database to save %d items)",
263
+ oDatabase->get_save_size() );
264
+ werror( "Shutting down ! (waiting for database to save %d items)\n",
265
+ oDatabase->get_save_size() );
266
+ oDatabase->log_save_queue( 1000 );
267
oDatabase->wait_for_db_lock();
268
+ MESSAGE("Database finished, exiting.");
269
+ werror("Database finished, exiting.\n");
273
static private void got_hangup(int sig)
275
- MESSAGE("sTeam: hangup signal received...");
276
+ MESSAGE( "Shutting down ! (waiting for database to save %d items)",
277
+ oDatabase->get_save_size() );
278
+ werror( "Shutting down ! (waiting for database to save %d items)\n",
279
+ oDatabase->get_save_size() );
280
+ oDatabase->log_save_queue( 1000 );
281
+ oDatabase->wait_for_db_lock();
282
+ MESSAGE("Database finished, exiting.");
283
+ werror("Database finished, exiting.\n");
288
@@ -685,19 +699,13 @@
289
add_constant(cfg, 1);
292
- mixed err = catch {
293
- Stdio.File f=Stdio.File (pidfile,"wac");
294
- f->write(" " + (string)pid);
298
- FATAL("There was an error writting the pidfile...\n");
300
- err = catch(_stderr = Stdio.File(mConfigs["logdir"]+"/errors.log", "r"));
301
+ mixed err = catch(_stderr = Stdio.File(mConfigs["logdir"]+"/errors.log", "r"));
303
MESSAGE("Failed to open %s/errors.log", mConfigs["logdir"]);
305
- signal(signum("SIGQUIT"), got_kill);
306
+ signal(signum("QUIT"), got_kill);
307
+ signal(signum("TERM"), got_kill);
308
signal(signum("SIGHUP"), got_hangup);
309
signal(signum("SIGINT"), got_hangup);
310
return start_server();
311
diff -urNad steam-2.2.31~/stop steam-2.2.31/stop
312
--- steam-2.2.31~/stop 2006-03-27 14:40:05.000000000 +0200
313
+++ steam-2.2.31/stop 2006-11-21 15:59:14.000000000 +0100
317
+cat_func="head -n 1"
320
+ [ "$tmp_option" == "--force" ] && cat_func='cat'
321
# Extract options and values (format: option=value):
322
option=${tmp_option%%=*}
323
value=${tmp_option#*=}
325
[ "$option" == "--pid" ] && pidfile=$value
326
[ "$option" == "--pidfile" ] && pidfile=$value
328
-[ -e "$pidfile" ] && kill `cat $pidfile`
329
-[ -e "$pidfile" ] && rm -f "$pidfile"
330
+[ -e "$pidfile" ] && kill `$cat_func $pidfile`
331
+while test -e "$pidfile"
333
+ sleep 1 # wait for server to finish shutdown
335
+#[ -e "$pidfile" ] && exit 1 # pidfile is deleted by loader