GTK+ Forums

Discussion forum for GTK+ and Programming. Ask questions, troubleshoot problems, view and post example code, or express your opinions.
It is currently Mon Nov 24, 2014 9:34 pm

All times are UTC




Post new topic Reply to topic  [ 8 posts ] 
Author Message
 Post subject: Fork, thread, exec lots of confusion.
PostPosted: Wed Jan 25, 2012 10:20 pm 
Offline
Familiar Face

Joined: Sun Jan 01, 2012 7:28 pm
Posts: 14
Location: Québec
I managed to set up a form with Forward and Reverse buttons to control my motor. [SOLVED] g_signal_connect - Trying to understand.

Now I would like a Stop button. Of course the problem is I use system(motorCommand) to activate the motor. That works but I cannot use the gui while the motor is spinning. The button remains pushed and I cannot do anything.

I tried fork then execlp but then I get this error as soon as I move the mouse.
Code:
[xcb] Unknown sequence number while processing queue
[xcb] Most likely this is a multi-threaded client and XInitThreads has not been called
[xcb] Aborting, sorry about that.
button: xcb_io.c:273: poll_for_event: Assertion `!xcb_xlib_threads_sequence_lost' failed.
[xcb] Unknown sequence number while processing queue
[xcb] Most likely this is a multi-threaded client and XInitThreads has not been called
[xcb] Aborting, sorry about that.
button: xcb_io.c:273: poll_for_event: Assertion `!xcb_xlib_threads_sequence_lost' failed.
Aborted


I have seen g_spawn_async_with_pipes in glib, but there are so many parameters that I don't quite understand and I am not convinced that would be the solution.


Top
 Profile  
 
 Post subject: Re: Fork, thread, exec lots of confusion.
PostPosted: Wed Jan 25, 2012 11:15 pm 
Offline
Never Seen the Sunlight

Joined: Mon Apr 28, 2008 5:52 am
Posts: 778
Location: UK
Hi,

Looking at your error report, I would presume that you have used the fork() and exec() functions incorrectly. The system() function and the Glib g_spawn set of functions all use fork() / exec() to launch a programme under Unix systems, it is different under MS Windows.

Yes g_spawn_async_with_pipes() has a lot of arguments, but that does give you a large amount of control over the application you are about to launch, including setting up communication pipes, a way to watch for when the application has exited, setting the environment. There are simpler versions of this function, g_spawn_async () this is similar but without the pipe and if you want very simple g_spawn_command_line_async (). Which one you need depends on if you want to communicate with the launched application while it is running, if you want to watch if it is still running or to just run it and leave the launched application to do its own thing.

Another thing you may need to think about is if the launched application locks the stepper motor for its own use only while it is running. So launching another may fail as it could be denied access to the motor.

_________________
E.


Top
 Profile  
 
 Post subject: Re: Fork, thread, exec lots of confusion.
PostPosted: Thu Jan 26, 2012 12:04 am 
Offline
Familiar Face

Joined: Sun Jan 01, 2012 7:28 pm
Posts: 14
Location: Québec
Hum indeed I used fork() and exec(), I really don't know what I could be missing.
Here is what I tried. I am on Linux, you probably figured this out.
Code:
int run_motor(int posn)
{
    //gchar motorCommand[255]="";
    //gchar *const motor_args[]={"stepper",posn, 1, 0};
    printf("Starting motor\n");
    printf("Entered position =%i=\n",posn);
    //pid_t motor_pid;

    if (posn==0)
    {
        puts("Let's read commands from file");
        system("./stepper<data.txt");
    }
    else
    { 
        puts("Let's move to posn...");
        //sprintf(motorCommand, "./stepper %i 1 %i", posn, 0 );
        //sprintf(motorCommand, "%i 1 %i", posn, 0 );
        fork();
        execlp("stepper","stepper", 1000, 1, 0, NULL);
      //system(motorCommand);
      //g_spawn_async(NULL,motor_args, NULL,G_SPAWN_SEARCH_PATH, NULL, NULL, NULL, NULL;
    }
    return 0;
}


Top
 Profile  
 
 Post subject: Re: Fork, thread, exec lots of confusion.
PostPosted: Thu Jan 26, 2012 9:20 am 
Offline
Never Seen the Sunlight

Joined: Mon Apr 28, 2008 5:52 am
Posts: 778
Location: UK
Yes you have used fork()/exec() calls incorrectly.

What fork() does is create another copy of your process, so that you will have two copies of your current process. What is called the parent and the child, note that there are certain things that are not copied to the child process and the child will have its own process id. You have then called execlp(), this is supposed to replace the process with another application, but keeping many details including the process id. execlp() should not return if everything is OK, but if it does you have an error.

What I think has happened is that you have used fork() and that has succeeded in creating two processes. You have then called execlp() but in both cases (yes twice as it is being run in two processes) it has failed probably due to the arguments being passed to it being incorrect. You are now left with two processes trying to run the same GUI and confusing the X11 back end and it now does not know what order to apply the commands.

Code:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>

void example_run(void)
{
    pid_t pid;

    pid = fork();
    if (pid == 0) {
/* Here we are running as the child */
/* This should replace the child process */
        execlp("echo", "echo", "Hello world", (char *) NULL);
        printf("Exec failed\n");
        _exit(EXIT_FAILURE);
    } else if (pid > 0) {
/* Here we are running as the parent */
        printf("Fork success\n");
/* Do what you want from here in the original process
* you could pass on the process id, wait on the process id etc
*/
    } else {
        printf("Fork failed\n");
    }
}


As you can see this does make using g_spawn_async() seam simple in comparison. Here is your example corrected (but untested) using g_spawn_async(), and including setting up the arguments correctly. As you can see most of the arguments to the function call is ignored by simply passing a NULL to it. At some point you may want to use these for certain features.

Code:
int run_motor(int posn)
{
    printf("Starting motor\n");
    printf("Entered position =%i=\n",posn);

    if (posn==0)
    {
        puts("Let's read commands from file");
        system("./stepper<data.txt");
    }
    else
    {
        gchar *motor_args[6];

        puts("Let's move to posn...");

        motor_args[0] = "stepper";
        motor_args[1] = g_strdup_printf("%i", posn);
        motor_args[2] = "1";
        motor_args[3] = "0";
        motor_args[4] = NULL;

        g_spawn_async(NULL, motor_args, NULL, G_SPAWN_SEARCH_PATH, NULL, NULL, NULL, NULL, NULL);

        g_free(motor_args[1]);
    }
    return 0;
}

_________________
E.


Top
 Profile  
 
 Post subject: Re: Fork, thread, exec lots of confusion.
PostPosted: Thu Jan 26, 2012 6:12 pm 
Offline
Familiar Face

Joined: Sun Jan 01, 2012 7:28 pm
Posts: 14
Location: Québec
Ok now I see.
I knew the fork itself was working as I implement some switch case checking after I posted, but my mind was stuck. I knew that there was two processes running but how the heck do I tell or know which process gets the "exec" function call... I cannot try it at the moment, but I bet if I put the execlp() in the proper switch statement, it will work.

I will try the g_spawn_async() as soon as I have a chance too.


Top
 Profile  
 
 Post subject: Re: Fork, thread, exec lots of confusion.
PostPosted: Thu Jan 26, 2012 6:37 pm 
Offline
Never Seen the Sunlight

Joined: Mon Apr 28, 2008 5:52 am
Posts: 778
Location: UK
I would stick with g_spawn_async() as this is simpler to use than the combination of fork()/exec() and does the right thing for you. If you want to use the fork()/exec() combination then check out the manual pages that should be installed on your system and the related pages. There should be examples there to.

_________________
E.


Top
 Profile  
 
 Post subject: Re: Fork, thread, exec lots of confusion.
PostPosted: Thu Jan 26, 2012 7:47 pm 
Offline
Familiar Face

Joined: Sun Jan 01, 2012 7:28 pm
Posts: 14
Location: Québec
Oh yes, for sure I will stick to g_spawn_async(). I still want to try both, just for an academic point of view. And convince myself :). I did look at the man exec, there was not much exemples there. But anyway, with what you provided above, if I cannot make it work with that, I never will. More to follow on that.


Top
 Profile  
 
 Post subject: Re: Fork, thread, exec lots of confusion.
PostPosted: Sun Jan 29, 2012 5:11 pm 
Offline
Familiar Face

Joined: Sun Jan 01, 2012 7:28 pm
Posts: 14
Location: Québec
errol wrote:
I would stick with g_spawn_async() as this is simpler to use than the combination of fork()/exec() and does the right thing for you. If you want to use the fork()/exec() combination then check out the manual pages that should be installed on your system and the related pages. There should be examples there to.

I went as per your recommendations. Slight problem though. I think I solved it, just not sure if it is the best approach. Problem is when I click Forward, motor starts. While it spins, I can click on Reverse but the Reverse action only take place when the Forward action is complete. Actually a new process is created every time I click Forward or Reverse. So I need a way to get the process number, and kill it. But if I kill it too early, motor does not have time to start. So I put a sleep(1).
Code:
int run_motor(int posn)
{
    printf("Starting motor\n");
    printf("Entered position =%i=\n",posn);

    if (posn==0)
    {
        puts("Let's read commands from file");
        system("./stepper<data.txt");
    }
    else
    { 
        gchar *motor_args[6];
        GPid motor_pid;
        puts("Let's move to posn...");

        motor_args[0] = "./stepper";
        motor_args[1] = g_strdup_printf("%i", posn);
        motor_args[2] = "1";
        motor_args[3] = "0";
        motor_args[4] = NULL;

        g_spawn_async(NULL, motor_args, NULL, G_SPAWN_SEARCH_PATH, NULL, NULL, &motor_pid, NULL);
        printf("Motor pis is...%i\n",motor_pid);
        sleep(1); //Let the motor start
        kill(motor_pid, 15); //Kill the process so another one can take over...
        g_free(motor_args[1]);
    }
    return 0;
}


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 8 posts ] 

All times are UTC


Who is online

Users browsing this forum: No registered users and 3 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group