aboutsummaryrefslogtreecommitdiffstats
path: root/pseudo_client.c
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 /pseudo_client.c
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.)
Diffstat (limited to 'pseudo_client.c')
-rw-r--r--pseudo_client.c85
1 files changed, 46 insertions, 39 deletions
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