Re: about two-way pipes or threads
- From: Ronald Bultje <rbultje ronald bitfreak net>
- To: gtk-list gnome org
- Subject: Re: about two-way pipes or threads
- Date: Mon, 12 Feb 2001 01:15:43 +0100
Hey there,
Okay. I included some of the functions in here.
It's quite a lot. Let's hope this is enough...
Let's go with the source. Here it is (the stuff that matters, I think). If
you need more, ask again :)
===========================================================
#include <pthread.h>
#include <gtk/gtk.h>
#include <glib.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <gdk/gdkx.h>
#include <signal.h>
[.......]
int pid;
gint studio_lavrec_gint;
int inp_pipe, out_pipe;
void lavrec_input(gpointer data, gint source, GdkInputCondition condition)
{
char *p;
char buf[129];
int len, numLines=0;
while ((p = read(inp_pipe, buf, 128)) != NULL)
{
len = strlen(buf);
if (len > 0)
buf[len-1] = '\0';
g_print("%s\n", buf);
numLines++;
return;
}
if ( numLines == 0 )
{
g_print("Lavrec completed\n");
gdk_input_remove(studio_lavrec_gint);
inp_pipe = -1;
studio_lavrec_gint = 0;
}
}
void create_child(char **args)
{
int ipipe[2], opipe[2];
int n;
if(pipe(ipipe)!=0 || pipe(opipe)!=0) { g_print("Error starting
lavrec: pipe != 0\n"); }
pid = fork();
if(pid<0) { g_print("Error starting lavrec: pid<0\n"); }
if (pid)
{
// We are the parent
inp_pipe = ipipe[0];
close(ipipe[1]);
out_pipe = opipe[1];
close(opipe[0]);
}
else
{
// We are the child
close(ipipe[0]);
close(opipe[1]);
close(0);
n = dup(opipe[0]);
if(n!=0) exit(1);
close(opipe[0]);
close(1);
n = dup(ipipe[1]);
if(n!=1) exit(1);
close(ipipe[1]);
close(2);
n = dup(1);
if(n!=2) exit(1);
execvp(args[0],args);
}
}
void emulate_enter()
{
write(out_pipe, "\n", 1);
capturing = TRUE;
}
void emulate_ctrl_c()
{
kill(pid, SIGINT);
gtk_signal_disconnect(GTK_OBJECT (start_button), start_button_id);
gtk_signal_disconnect(GTK_OBJECT (stop_button), stop_button_id);
gdk_input_remove(studio_lavrec_gint);
inp_pipe = -1;
studio_lavrec_gint = 0;
capturing = FALSE;
capturing_init = FALSE;
}
void write_result(GtkWidget *widget, gpointer data)
{
char *args[2];
/* [.....] Lots of calls to find out what the exact command
should be (=args, deepnds on user input)[...] */
start_lavrec();
args[0] = command->str;
args[1] = 0;
create_child(args);
studio_lavrec_gint = gdk_input_add(inp_pipe, GDK_INPUT_READ,
lavrec_input," " );
start_button_id = gtk_signal_connect(GTK_OBJECT(start_button),
"clicked", GTK_SIGNAL_FUNC(emulate_enter), NULL);
stop_button_id = gtk_signal_connect(GTK_OBJECT(stop_button),
"clicked", GTK_SIGNAL_FUNC(emulate_ctrl_c), NULL);
}
GtkWidget *create_buttons(GtkWidget *vbox)
{
GtkWidget *hbox, *label, *button;
[.......]
init_button = gtk_button_new_with_label("Initialize capture");
init_button_id = gtk_signal_connect(GTK_OBJECT(init_button),
"clicked", GTK_SIGNAL_FUNC(write_result), NULL);
gtk_box_pack_start (GTK_BOX (vbox), init_button, FALSE, FALSE, 0);
gtk_widget_show(init_button);
[......]
start_button = gtk_button_new_with_label("[Start]");
gtk_box_pack_start (GTK_BOX (hbox), start_button, TRUE, TRUE, 0);
gtk_widget_show(start_button);
[....]
stop_button = gtk_button_new_with_label("[Stop]");
gtk_box_pack_start (GTK_BOX (hbox), stop_button, TRUE, TRUE, 0);
gtk_widget_show(stop_button);
}
int main( int argc, char *argv[] )
{
GtkWidget *vbox, *tv, *mainbox, *hbox, *hbox2, *pixmap_w, *label,
*button;
GdkPixmap *pixmap;
GdkBitmap *mask;
GtkStyle *style;
[......]
gtk_init(&argc, &argv);
capturing_init = FALSE;
capturing = FALSE;
[....]
vbox = create_buttons(vbox);
[.....]
gtk_widget_show(window);
gdk_threads_enter();
gtk_main ();
gdk_threads_leave();
return(0);
}
=========================================================
On 2001.02.10 16:18:50 +0100 Paul Davis wrote:
> In message <20010210152217 C2939 tux bitfreak net>you write:
> >Hi there,
> >
> >I have tried a few things to do what I want. I already asked some
> questions
> >on threading, on creating/using pipes, but I just cannot figure it out.
> >
> >What I want is to have control over another application. I need to write
> >data to it's stdin and read it's stdout. I figured that using the "lower
> >level pipes" would be nice here, but they don't work a bit. I get all
> kind
> >of weird errors, output is only grabbed after the application has
> quitted.
> >It is probably necessary to flush this applications output and/or flush
> my
> >own grabbing of that output, but anyway, it didn't work (yet). Also, in
> >some cases, I get xlib-async errors.
>
> Given that I have at least 3 of my own applications and can name at
> least half a dozen others that use this approach, I can safely say
> that the only thing with whatever you're doing is is probably a
> trivial error. This approach works perfectly, and any errors you are
> getting are caused by some lac of understanding.
>
> Why don't you send us a suitably stripped down version of the code,
> and someone (me, or someone else) can comment on it.
>
> >Internet says that xlib-async errors means that xlib is not thread-safe.
> So
> >is it safe at all to use threads when I get this error as a result?
>
> You won't get this error if you bracket all calls to X/GDK/GTK with
>
> gdk_threads_enter();
> ...
> gdk_threads_leave();
>
> as the FAQ instructs.
>
> --p
>
>
--
---------------------------------------------------.
-- .-. | Ronald Bultje |
-- /V\ | Running: Linux 2.4.1 and OpenBSD 2.8 |
-- // \\ | E-mail : rbultje ronald bitfreak net |
-- /( )\ | WWW : http://ronald.bitfreak.net/ |
-- ^^-^^ | *** Warning: Unix Addicted *** |
---------------------------------------------------'
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]