aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPeter Seebach <peter.seebach@windriver.com>2016-02-08 17:09:11 -0600
committerPeter Seebach <peter.seebach@windriver.com>2016-02-08 17:09:11 -0600
commitf0d2cb7bb944b7086ba86547bbb9a33ce7745ba6 (patch)
tree6e83c7c09f3e64363b5ed36fc8043be39e215f05
parentb73342cfa3be4dc4a6b960f44e5181ab655b16bd (diff)
downloadpseudo-f0d2cb7bb944b7086ba86547bbb9a33ce7745ba6.tar.gz
pseudo-f0d2cb7bb944b7086ba86547bbb9a33ce7745ba6.tar.bz2
pseudo-f0d2cb7bb944b7086ba86547bbb9a33ce7745ba6.zip
pseudo_client.c: rework of startup logic in client
There's a possible race condition if multiple clients try to start while the server's down, especially if it's shutting down and thus holding a lock but ignoring them. Logic altered to retry more often, at greater intervals. Also, we are fine with being unable to spawn the server, because that can happen if another client spawned it successfully. So we just retry sending the message in a bit if we couldn't spawn a server, or immediately if we could. (Because "could" spawn a server includes successfully communicating with the newly-spawned server; the server-side code makes sure that the child process won't exit before we expect such attempts to work, even if they take a while.)
-rw-r--r--ChangeLog.txt1
-rw-r--r--pseudo_client.c85
2 files changed, 47 insertions, 39 deletions
diff --git a/ChangeLog.txt b/ChangeLog.txt
index 404923f..30e5d02 100644
--- a/ChangeLog.txt
+++ b/ChangeLog.txt
@@ -1,6 +1,7 @@
2016-02-08:
* (seebs) require -S to shutdown server when running a command.
* (seebs) improve logic for server shutdowns, increase short timeout
+ * (seebs) rework client server-spawning logic significantly
2016-02-05:
* (seebs) don't abort search for server on first try.
diff --git a/pseudo_client.c b/pseudo_client.c
index 89c0c07..00d18d0 100644
--- a/pseudo_client.c
+++ b/pseudo_client.c
@@ -1201,9 +1201,6 @@ pseudo_client_setup(void) {
}
pseudo_debug(PDBGF_CLIENT, "server seems to be gone, trying to restart\n");
if (client_spawn_server()) {
- int ms = (getpid() % 5) + 3;
- struct timespec delay = { .tv_sec = 0, .tv_nsec = ms * 1000000 };
- nanosleep(&delay, NULL);
pseudo_debug(PDBGF_CLIENT, "failed to spawn server, waiting for retry.\n");
return 1;
@@ -1217,6 +1214,7 @@ pseudo_client_setup(void) {
return 1;
}
+#define PSEUDO_RETRIES 50
static pseudo_msg_t *
pseudo_client_request(pseudo_msg_t *msg, size_t len, const char *path) {
pseudo_msg_t *response = 0;
@@ -1226,46 +1224,55 @@ pseudo_client_request(pseudo_msg_t *msg, size_t len, const char *path) {
if (!msg)
return 0;
- do {
- do {
- pseudo_debug(PDBGF_CLIENT | PDBGF_VERBOSE, "sending a message: ino %llu\n",
- (unsigned long long) msg->ino);
- rc = pseudo_msg_send(connect_fd, msg, len, path);
- if (rc != 0) {
- pseudo_debug(PDBGF_CLIENT | PDBGF_VERBOSE, "msg_send: %d%s\n",
- rc,
- rc == -1 ? " (sigpipe)" :
- " (short write)");
- ++tries;
- if (tries > 3) {
- pseudo_debug(PDBGF_CLIENT, "Can't get server going again.\n");
+ /* Try to send a message. If sending fails, try to spawn a server,
+ * and whether or not we succeed, wait a little bit and retry sending.
+ * It's okay if we can't start a server sometimes, because another
+ * client may have done it.
+ */
+ for (tries = 0; tries < PSEUDO_RETRIES; ++tries) {
+ pseudo_debug(PDBGF_CLIENT | PDBGF_VERBOSE, "sending a message: ino %llu\n",
+ (unsigned long long) msg->ino);
+ rc = pseudo_msg_send(connect_fd, msg, len, path);
+ if (rc != 0) {
+ pseudo_debug(PDBGF_CLIENT | PDBGF_VERBOSE, "msg_send: %d%s\n",
+ rc,
+ rc == -1 ? " (sigpipe)" :
+ " (short write)");
+ pseudo_debug(PDBGF_CLIENT, "trying to get server, try %d\n", tries);
+ /* try to open server; if we fail, wait a bit before
+ * retry.
+ */
+ if (pseudo_client_setup()) {
+ int ms = (getpid() % 5) + 3 + tries;
+ struct timespec delay = { .tv_sec = 0, .tv_nsec = ms * 1000000 };
+ nanosleep(&delay, NULL);
+ }
+ continue;
+ }
+ /* note "continue" above; we only get here if rc was 0,
+ * indicating a successful send.
+ */
+ pseudo_debug(PDBGF_CLIENT | PDBGF_VERBOSE, "sent!\n");
+ if (msg->type != PSEUDO_MSG_FASTOP) {
+ response = pseudo_msg_receive(connect_fd);
+ if (!response) {
+ pseudo_debug(PDBGF_CLIENT, "expected response did not occur; retrying\n");
+ } else {
+ if (response->type != PSEUDO_MSG_ACK) {
+ pseudo_debug(PDBGF_CLIENT, "got non-ack response %d\n", response->type);
return 0;
+ } else {
+ pseudo_debug(PDBGF_CLIENT | PDBGF_VERBOSE, "got response type %d\n", response->type);
+ return response;
}
- pseudo_debug(PDBGF_CLIENT, "trying to get server, try %d\n", tries);
- pseudo_client_setup();
}
- } while (rc != 0);
- pseudo_debug(PDBGF_CLIENT | PDBGF_VERBOSE, "sent!\n");
- if (msg->type != PSEUDO_MSG_FASTOP) {
- response = pseudo_msg_receive(connect_fd);
- if (!response) {
- ++tries;
- if (tries > 3) {
- pseudo_debug(PDBGF_CLIENT, "Can't get responses.\n");
- return 0;
- }
- }
- } else {
- return 0;
- }
- } while (response == 0);
- if (response->type != PSEUDO_MSG_ACK) {
- pseudo_debug(PDBGF_CLIENT, "got non-ack response %d\n", response->type);
- return 0;
- } else {
- pseudo_debug(PDBGF_CLIENT | PDBGF_VERBOSE, "got response type %d\n", response->type);
+ } else {
+ return 0;
+ }
}
- return response;
+ pseudo_debug(PDBGF_CLIENT, "server connection persistently failed, aborting.\n");
+ abort();
+ return 0;
}
int