]> rtime.felk.cvut.cz Git - canping.git/commitdiff
Added option to go to background
authorMichal Sojka <sojkam1@fel.cvut.cz>
Thu, 11 Jun 2009 16:20:18 +0000 (18:20 +0200)
committerMichal Sojka <sojkam1@fel.cvut.cz>
Thu, 11 Jun 2009 16:20:18 +0000 (18:20 +0200)
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

index 21239768bae5f50ab7295f984ca4e69f68de5c3a..8de0af5b9a1fcf315ddb1bf4dbf1cc87c0782d40 100644 (file)
@@ -31,6 +31,8 @@
 #include <ul_list.h>
 #include <errno.h>
 #include <semaphore.h>
+#include <stdbool.h>
+#include <error.h>
 
 /* 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 <master threads> [other options]\n"
               "       canping -s <slave threads> [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) {