Re: about two-way pipes or threads



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]