aboutsummaryrefslogtreecommitdiff
path: root/src/arm/gnunet-service-arm.c
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2015-10-18 21:54:11 +0000
committerChristian Grothoff <christian@grothoff.org>2015-10-18 21:54:11 +0000
commit770959a6e7ed92e09d61553e170e3dc6053f0355 (patch)
tree667b68f58923cf09d6026363362fdae057e4907a /src/arm/gnunet-service-arm.c
parent8af92fb15d1166dbd79e40a53c3a785ca8c0346b (diff)
downloadgnunet-770959a6e7ed92e09d61553e170e3dc6053f0355.tar.gz
gnunet-770959a6e7ed92e09d61553e170e3dc6053f0355.zip
-fix
Diffstat (limited to 'src/arm/gnunet-service-arm.c')
-rw-r--r--src/arm/gnunet-service-arm.c304
1 files changed, 164 insertions, 140 deletions
diff --git a/src/arm/gnunet-service-arm.c b/src/arm/gnunet-service-arm.c
index b8cda5945..b3bf168f1 100644
--- a/src/arm/gnunet-service-arm.c
+++ b/src/arm/gnunet-service-arm.c
@@ -1,6 +1,6 @@
1/* 1/*
2 This file is part of GNUnet. 2 This file is part of GNUnet.
3 Copyright (C) 2009, 2010, 2011 Christian Grothoff (and other contributing authors) 3 Copyright (C) 2009, 2010, 2011, 2015 Christian Grothoff (and other contributing authors)
4 4
5 GNUnet is free software; you can redistribute it and/or modify 5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published 6 it under the terms of the GNU General Public License as published
@@ -1046,7 +1046,7 @@ shutdown_task (void *cls,
1046 { 1046 {
1047 GNUNET_CONTAINER_DLL_remove (pos->listen_head, 1047 GNUNET_CONTAINER_DLL_remove (pos->listen_head,
1048 pos->listen_tail, sli); 1048 pos->listen_tail, sli);
1049 if (sli->accept_task != NULL) 1049 if (NULL != sli->accept_task)
1050 { 1050 {
1051 GNUNET_SCHEDULER_cancel (sli->accept_task); 1051 GNUNET_SCHEDULER_cancel (sli->accept_task);
1052 sli->accept_task = NULL; 1052 sli->accept_task = NULL;
@@ -1168,7 +1168,8 @@ delayed_restart_task (void *cls,
1168 * @param tc context 1168 * @param tc context
1169 */ 1169 */
1170static void 1170static void
1171maint_child_death (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) 1171maint_child_death (void *cls,
1172 const struct GNUNET_SCHEDULER_TaskContext *tc)
1172{ 1173{
1173 struct ServiceList *pos; 1174 struct ServiceList *pos;
1174 struct ServiceList *next; 1175 struct ServiceList *next;
@@ -1184,172 +1185,195 @@ maint_child_death (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
1184 pr = GNUNET_DISK_pipe_handle (sigpipe, GNUNET_DISK_PIPE_END_READ); 1185 pr = GNUNET_DISK_pipe_handle (sigpipe, GNUNET_DISK_PIPE_END_READ);
1185 child_death_task = NULL; 1186 child_death_task = NULL;
1186 if (0 == (tc->reason & GNUNET_SCHEDULER_REASON_READ_READY)) 1187 if (0 == (tc->reason & GNUNET_SCHEDULER_REASON_READ_READY))
1187 { 1188 {
1188 /* shutdown scheduled us, ignore! */ 1189 /* shutdown scheduled us, ignore! */
1189 child_death_task = 1190 child_death_task =
1190 GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_UNIT_FOREVER_REL, 1191 GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_UNIT_FOREVER_REL,
1191 pr, &maint_child_death, NULL); 1192 pr,
1192 return; 1193 &maint_child_death,
1193 } 1194 NULL);
1195 return;
1196 }
1194 /* consume the signal */ 1197 /* consume the signal */
1195 GNUNET_break (0 < GNUNET_DISK_file_read (pr, &c, sizeof (c))); 1198 GNUNET_break (0 < GNUNET_DISK_file_read (pr, &c, sizeof (c)));
1196 1199
1197 /* check for services that died (WAITPID) */ 1200 /* check for services that died (WAITPID) */
1198 next = running_head; 1201 next = running_head;
1199 while (NULL != (pos = next)) 1202 while (NULL != (pos = next))
1200 { 1203 {
1201 next = pos->next; 1204 next = pos->next;
1202 1205
1203 if (pos->proc == NULL) 1206 if (NULL == pos->proc)
1204 { 1207 {
1205 if (GNUNET_YES == in_shutdown) 1208 if (GNUNET_YES == in_shutdown)
1206 free_service (pos); 1209 free_service (pos);
1207 continue; 1210 continue;
1208 } 1211 }
1209#if HAVE_WAIT4 1212#if HAVE_WAIT4
1210 if (NULL != wait_file) 1213 if (NULL != wait_file)
1214 {
1215 /* need to use 'wait4()' to obtain and log performance data */
1216 struct rusage ru;
1217 int status;
1218 pid_t pid;
1219
1220 pid = GNUNET_OS_process_get_pid (pos->proc);
1221 ret = wait4 (pid,
1222 &status,
1223 WNOHANG,
1224 &ru);
1225 if (ret <= 0)
1226 continue; /* no process done */
1227 if (WIFEXITED (status))
1211 { 1228 {
1212 /* need to use 'wait4()' to obtain and log performance data */ 1229 statusType = GNUNET_OS_PROCESS_EXITED;
1213 struct rusage ru; 1230 statusCode = WEXITSTATUS (status);
1214 int status;
1215 pid_t pid;
1216
1217 pid = GNUNET_OS_process_get_pid (pos->proc);
1218 ret = wait4 (pid,
1219 &status,
1220 WNOHANG,
1221 &ru);
1222 if (ret <= 0)
1223 continue; /* no process done */
1224 if (WIFEXITED (status))
1225 {
1226 statusType = GNUNET_OS_PROCESS_EXITED;
1227 statusCode = WEXITSTATUS (status);
1228 }
1229 else if (WIFSIGNALED (status))
1230 {
1231 statusType = GNUNET_OS_PROCESS_SIGNALED;
1232 statusCode = WTERMSIG (status);
1233 }
1234 else if (WIFSTOPPED (status))
1235 {
1236 statusType = GNUNET_OS_PROCESS_SIGNALED;
1237 statusCode = WSTOPSIG (status);
1238 }
1239#ifdef WIFCONTINUED
1240 else if (WIFCONTINUED (status))
1241 {
1242 statusType = GNUNET_OS_PROCESS_RUNNING;
1243 statusCode = 0;
1244 }
1245#endif
1246 else
1247 {
1248 statusType = GNUNET_OS_PROCESS_UNKNOWN;
1249 statusCode = 0;
1250 }
1251 if ( (GNUNET_OS_PROCESS_EXITED == statusType) ||
1252 (GNUNET_OS_PROCESS_SIGNALED == statusType) )
1253 {
1254 fprintf (wait_file,
1255 "%s(%u) %llu.%llu %llu.%llu %llu %llu %llu %llu %llu\n",
1256 pos->binary,
1257 (unsigned int) pid,
1258 (unsigned long long) ru.ru_utime.tv_sec,
1259 (unsigned long long) ru.ru_utime.tv_usec,
1260 (unsigned long long) ru.ru_stime.tv_sec,
1261 (unsigned long long) ru.ru_stime.tv_usec,
1262 (unsigned long long) ru.ru_maxrss,
1263 (unsigned long long) ru.ru_inblock,
1264 (unsigned long long) ru.ru_oublock,
1265 (unsigned long long) ru.ru_nvcsw,
1266 (unsigned long long) ru.ru_nivcsw);
1267 }
1268 } 1231 }
1269 else /* continue with #else */ 1232 else if (WIFSIGNALED (status))
1270#else
1271 if ((GNUNET_SYSERR ==
1272 (ret =
1273 GNUNET_OS_process_status (pos->proc, &statusType, &statusCode))) ||
1274 ((ret == GNUNET_NO) ||
1275 (statusType == GNUNET_OS_PROCESS_STOPPED) ||
1276 (statusType == GNUNET_OS_PROCESS_RUNNING) ) )
1277 continue;
1278#endif
1279 if (statusType == GNUNET_OS_PROCESS_EXITED)
1280 { 1233 {
1281 statstr = _( /* process termination method */ "exit"); 1234 statusType = GNUNET_OS_PROCESS_SIGNALED;
1282 statcode = statusCode; 1235 statusCode = WTERMSIG (status);
1283 } 1236 }
1284 else if (statusType == GNUNET_OS_PROCESS_SIGNALED) 1237 else if (WIFSTOPPED (status))
1285 { 1238 {
1286 statstr = _( /* process termination method */ "signal"); 1239 statusType = GNUNET_OS_PROCESS_SIGNALED;
1287 statcode = statusCode; 1240 statusCode = WSTOPSIG (status);
1288 } 1241 }
1289 else 1242#ifdef WIFCONTINUED
1243 else if (WIFCONTINUED (status))
1290 { 1244 {
1291 statstr = _( /* process termination method */ "unknown"); 1245 statusType = GNUNET_OS_PROCESS_RUNNING;
1292 statcode = 0; 1246 statusCode = 0;
1293 } 1247 }
1294 if (0 != pos->killed_at.abs_value_us) 1248#endif
1249 else
1295 { 1250 {
1296 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 1251 statusType = GNUNET_OS_PROCESS_UNKNOWN;
1297 _("Service `%s' took %s to terminate\n"), 1252 statusCode = 0;
1298 pos->name,
1299 GNUNET_STRINGS_relative_time_to_string (GNUNET_TIME_absolute_get_duration (pos->killed_at), GNUNET_YES));
1300 } 1253 }
1301 GNUNET_OS_process_destroy (pos->proc); 1254 if ( (GNUNET_OS_PROCESS_EXITED == statusType) ||
1302 pos->proc = NULL; 1255 (GNUNET_OS_PROCESS_SIGNALED == statusType) )
1303 broadcast_status (pos->name, GNUNET_ARM_SERVICE_STOPPED, NULL);
1304 if (NULL != pos->killing_client)
1305 { 1256 {
1306 signal_result (pos->killing_client, pos->name, 1257 fprintf (wait_file,
1307 pos->killing_client_request_id, GNUNET_ARM_RESULT_STOPPED); 1258 "%s(%u) %llu.%llu %llu.%llu %llu %llu %llu %llu %llu\n",
1308 GNUNET_SERVER_client_drop (pos->killing_client); 1259 pos->binary,
1309 pos->killing_client = NULL; 1260 (unsigned int) pid,
1310 pos->killing_client_request_id = 0; 1261 (unsigned long long) ru.ru_utime.tv_sec,
1262 (unsigned long long) ru.ru_utime.tv_usec,
1263 (unsigned long long) ru.ru_stime.tv_sec,
1264 (unsigned long long) ru.ru_stime.tv_usec,
1265 (unsigned long long) ru.ru_maxrss,
1266 (unsigned long long) ru.ru_inblock,
1267 (unsigned long long) ru.ru_oublock,
1268 (unsigned long long) ru.ru_nvcsw,
1269 (unsigned long long) ru.ru_nivcsw);
1311 } 1270 }
1312 if (GNUNET_YES != in_shutdown) 1271 }
1272 else /* continue with JUST this "if" as "else" (intentionally no brackets!) */
1273#endif
1274 if ( (GNUNET_SYSERR ==
1275 (ret =
1276 GNUNET_OS_process_status (pos->proc,
1277 &statusType,
1278 &statusCode))) ||
1279 (ret == GNUNET_NO) ||
1280 (statusType == GNUNET_OS_PROCESS_STOPPED) ||
1281 (statusType == GNUNET_OS_PROCESS_UNKNOWN) ||
1282 (statusType == GNUNET_OS_PROCESS_RUNNING) )
1283 continue;
1284 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1285 "Running with %d/%d\n",
1286 statusType,
1287 statusCode);
1288
1289 if (statusType == GNUNET_OS_PROCESS_EXITED)
1290 {
1291 statstr = _( /* process termination method */ "exit");
1292 statcode = statusCode;
1293 }
1294 else if (statusType == GNUNET_OS_PROCESS_SIGNALED)
1295 {
1296 statstr = _( /* process termination method */ "signal");
1297 statcode = statusCode;
1298 }
1299 else
1300 {
1301 statstr = _( /* process termination method */ "unknown");
1302 statcode = 0;
1303 }
1304 if (0 != pos->killed_at.abs_value_us)
1305 {
1306 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1307 _("Service `%s' took %s to terminate\n"),
1308 pos->name,
1309 GNUNET_STRINGS_relative_time_to_string (GNUNET_TIME_absolute_get_duration (pos->killed_at),
1310 GNUNET_YES));
1311 }
1312 GNUNET_OS_process_destroy (pos->proc);
1313 pos->proc = NULL;
1314 broadcast_status (pos->name,
1315 GNUNET_ARM_SERVICE_STOPPED,
1316 NULL);
1317 if (NULL != pos->killing_client)
1318 {
1319 signal_result (pos->killing_client, pos->name,
1320 pos->killing_client_request_id,
1321 GNUNET_ARM_RESULT_STOPPED);
1322 GNUNET_SERVER_client_drop (pos->killing_client);
1323 pos->killing_client = NULL;
1324 pos->killing_client_request_id = 0;
1325 }
1326 if (GNUNET_YES != in_shutdown)
1327 {
1328 if ( (statusType == GNUNET_OS_PROCESS_EXITED) &&
1329 (statcode == 0) )
1313 { 1330 {
1314 if ((statusType == GNUNET_OS_PROCESS_EXITED) && (statcode == 0)) 1331 /* process terminated normally, allow restart at any time */
1315 { 1332 pos->restart_at.abs_value_us = 0;
1316 /* process terminated normally, allow restart at any time */ 1333 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1317 pos->restart_at.abs_value_us = 0; 1334 _("Service `%s' terminated normally, will restart at any time\n"),
1318 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 1335 pos->name);
1319 _("Service `%s' terminated normally, will restart at any time\n"), 1336 /* process can still be re-started on-demand, ensure it is re-started if there is demand */
1320 pos->name); 1337 for (sli = pos->listen_head; NULL != sli; sli = sli->next)
1321 /* process can still be re-started on-demand, ensure it is re-started if there is demand */
1322 for (sli = pos->listen_head; NULL != sli; sli = sli->next)
1323 {
1324 GNUNET_break (NULL == sli->accept_task);
1325 sli->accept_task =
1326 GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL,
1327 sli->listen_socket, &accept_connection, sli);
1328 }
1329 }
1330 else
1331 { 1338 {
1332 if (0 == (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN)) 1339 GNUNET_break (NULL == sli->accept_task);
1333 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 1340 sli->accept_task =
1334 _("Service `%s' terminated with status %s/%d, will restart in %s\n"), 1341 GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL,
1335 pos->name, statstr, statcode, 1342 sli->listen_socket,
1336 GNUNET_STRINGS_relative_time_to_string (pos->backoff, GNUNET_YES)); 1343 &accept_connection,
1337 /* schedule restart */ 1344 sli);
1338 pos->restart_at = GNUNET_TIME_relative_to_absolute (pos->backoff);
1339 pos->backoff = GNUNET_TIME_STD_BACKOFF (pos->backoff);
1340 if (NULL != child_restart_task)
1341 GNUNET_SCHEDULER_cancel (child_restart_task);
1342 child_restart_task = GNUNET_SCHEDULER_add_with_priority (
1343 GNUNET_SCHEDULER_PRIORITY_IDLE, &delayed_restart_task, NULL);
1344 } 1345 }
1345 } 1346 }
1346 else 1347 else
1347 { 1348 {
1348 free_service (pos); 1349 if (0 == (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
1350 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1351 _("Service `%s' terminated with status %s/%d, will restart in %s\n"),
1352 pos->name,
1353 statstr,
1354 statcode,
1355 GNUNET_STRINGS_relative_time_to_string (pos->backoff,
1356 GNUNET_YES));
1357 /* schedule restart */
1358 pos->restart_at = GNUNET_TIME_relative_to_absolute (pos->backoff);
1359 pos->backoff = GNUNET_TIME_STD_BACKOFF (pos->backoff);
1360 if (NULL != child_restart_task)
1361 GNUNET_SCHEDULER_cancel (child_restart_task);
1362 child_restart_task
1363 = GNUNET_SCHEDULER_add_with_priority (GNUNET_SCHEDULER_PRIORITY_IDLE,
1364 &delayed_restart_task,
1365 NULL);
1349 } 1366 }
1350 } 1367 }
1368 else
1369 {
1370 free_service (pos);
1371 }
1372 }
1351 child_death_task = GNUNET_SCHEDULER_add_read_file ( 1373 child_death_task = GNUNET_SCHEDULER_add_read_file (
1352 GNUNET_TIME_UNIT_FOREVER_REL, pr, &maint_child_death, NULL); 1374 GNUNET_TIME_UNIT_FOREVER_REL,
1375 pr,
1376 &maint_child_death, NULL);
1353 if ((NULL == running_head) && (GNUNET_YES == in_shutdown)) 1377 if ((NULL == running_head) && (GNUNET_YES == in_shutdown))
1354 do_shutdown (); 1378 do_shutdown ();
1355 else if (GNUNET_YES == in_shutdown) 1379 else if (GNUNET_YES == in_shutdown)