From c2d88b9017e8a92eb34a3b6ceeccf66c9091c2e9 Mon Sep 17 00:00:00 2001 From: Michal Sojka Date: Thu, 11 Jun 2009 18:20:18 +0200 Subject: [PATCH] Added option to go to background This was necessary to safely start slave and master from the same script without inserting sleep(). With the new -b option, parent process returns, when the child is ready to receive (in case of slave) messages. --- src/vca_canping.c | 47 ++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 44 insertions(+), 3 deletions(-) diff --git a/src/vca_canping.c b/src/vca_canping.c index 2123976..8de0af5 100644 --- a/src/vca_canping.c +++ b/src/vca_canping.c @@ -31,6 +31,8 @@ #include #include #include +#include +#include /* TODO: Handle the case where there are more canping slaves running * on one CAN bus. */ @@ -98,6 +100,7 @@ int option_wait_ms = 1000; int option_timeout = 4; int option_open_once = 0; int option_synch_start = 0; +bool option_background = false; /* Lists */ typedef struct threads { @@ -404,6 +407,9 @@ void *slave_thread(void *arg) pongmsg.length = option_length; for (i=0; i < option_length; i++) pongmsg.data[i] = i; + /* Signal that I'm ready */ + sem_post(&ready_sem); + while (!IS_FINISH_FLAG()) { /* Receive a ping message */ pingmsg.flags=0; @@ -472,6 +478,9 @@ void start_slaves(int slaves, int first_id) pthread_create(&td->tid, NULL, slave_thread, (void *)td); dbg(2, "Slave thread: %p\n", (void *)td->tid); } + + /* Wait for all threads beeing ready */ + for (i = 0; i < slaves; i++) sem_wait(&ready_sem); } #ifdef WITH_RTPRIO @@ -501,6 +510,7 @@ void print_help(void) printf("Usage: canping -m [other options]\n" " canping -s [other options]\n\n" "Other options:\n" + " -b go to background (fork) after initialization, prints child PID\n" " -c count how many messages each master sends\n" " -d dev device (e.g. /dev/can1)\n" " -h print this help\n" @@ -526,9 +536,12 @@ int parse_options(int argc, char *argv[]) int c; opterr = 0; - while ((c = getopt (argc, argv, "c:d:hi:l:m:os:t:vw:yrR:")) != -1) + while ((c = getopt (argc, argv, "bc:d:hi:l:m:os:t:vw:yrR:")) != -1) switch (c) { + case 'b': + option_background = true; + break; case 'c': option_count = atoi(optarg); break; @@ -712,9 +725,37 @@ int main(int argc, char *argv[]) } } - if (option_masters) start_masters(option_masters, option_first_id); - if (option_slaves) start_slaves(option_slaves, option_first_id); + sem_t *child_ready; + int fork_ret = 0; + if ((child_ready = sem_open("canping", O_CREAT)) == NULL) + error(1, errno, "sem_open"); + if (option_background) { + /* Go to background when everything is ready */ + fork_ret = fork(); + if (fork_ret < 0) + error(1, errno, "Cannot go to background"); + if (fork_ret == 0) { + int devnull = open("/dev/null", O_WRONLY); + dup2(devnull, 1); + } + } + fprintf(stderr, "Common\n"); + if (fork_ret == 0) { + /* Child */ + fprintf(stderr, "Child starting childs\n"); + if (option_masters) start_masters(option_masters, option_first_id); + if (option_slaves) start_slaves(option_slaves, option_first_id); + sem_post(child_ready); + fprintf(stderr, "Child ready\n"); + } else { + /* Parent */ + fflush(stderr); + sem_wait(child_ready); + printf("%d\n", fork_ret); + exit(0); + } + wait_for_threads(); if (option_open_once) { -- 2.39.2