Hur får man ut all data ur en pty-pipe i Leopard?

Tråden skapades och har fått 1 svar. Det senaste inlägget skrevs .
1

Jag har slitit ett tag med ett jobbigt problem. Jag har en modul som jag använder för att göra GUI-wrappers till CLI-program. (I synnerhet är det hjärtat i den utvecklingmiljö jag utvecklar. Jag både kör kompileringar, filkopieringar och exekverar det resulterande programmet genom den.)

Allt funkar jättebra i Tiger. När barnprocessen stannar så dör den inte från förälderns synvinkel förrän alla data är utlästa. Perfekt. Men i Leopard så bara tvärdör den, och man kan inte läsa ut något alls!

Jag hoppas att det bara är någon flagga jag måste sätta eller något sådant. Finns det någon som känner igen problemet?

Bland det jag testat: signalhantering av SIGCHLD (signalen går fram men för sent, data är redan borta), SIGIO (signalen går inte fram alls), läsa av pty'n tills jag får inget och då testa med waitpid() (funkar enbart om jag pollar som en galning), etc etc.

Jag använder alltså forkpty(). Man kan tro att fork/pipe/exec skulle duga, men det funkar inte för dubbelriktad kommunikation. För enkelriktad går det någorlunda, men man får data klumpvis. Nej, inte bra. Bättre med forkpty() och det är vad böckerna säger också.

Om jag bara kan komma så långt att jag kan starta ett "hello world" och få hela utdata (dvs "hello world") enkelt och säkert utan att polla som en skållad råtta, då tror jag att problemet är löst. Men hur gör man?

Jag är ju inte den ende som gör program som anropar CLI-program heller! Någon som vet mer?

Ingen har en susning? Här är ett program som i mina tester visar problemet tydligt i Leopard:

#include <stdio.h>
#include <stdlib.h>
#include <util.h>
#include <stdint.h>
#include <fcntl.h>
#include <sys/filio.h>
#include <sys/errno.h>

void hello()
{
	printf("hello!\n");
	sleep(2); 
	printf("there!\n");
	sleep(2); 
	printf("BYE!\n");
}

int pty;
int done = 0;

void deadbeef(int a)
{
	int i;
	char name[256];
	
	i = 100;
	i = read(pty, name, i);
	if (i > 0) printf("Signal handler read %d %s\n", i, name);
	else printf("Signal handler read nothing\n");

	printf("aaarrrggh!\n");
	done = 1;
}

main()
{
	int pid, i, err;
	int mypid, ohyes;
	char s[256];
	
	if (( pid = forkpty( &(pty), NULL, NULL, NULL) ) < 0)
	{ // Failure
		printf( "Forking error\n");
		exit(-1);
	}
	if (0 == pid)
	{ // Slave - child process
		hello();
		exit( 0);
	}
	// Otherwise parent process
	
	int flags;
	// set file to non-blocking */
	flags = fcntl(pty, F_GETFL, 0);
	if (0 != fcntl(pty, F_SETFL, flags | O_NONBLOCK))
		printf( "fcntl error");
	
	if( SIG_ERR == signal( SIGCHLD, deadbeef))
		printf( "SIGCHLD error");
	
	// Wait for result
	while (!done)
	{
		i = 255; // buffer size
		i = read(pty, s, i);
		if (i>0)
		{
			s[i] = 0;
			printf("Read %d: <%s>\n", i, s);
		}
		else
			printf("*");
		sleep(1);
	}
	exit(0);
}

Testat på G5/PPC/Tiger (funkar bra), MacBook/PPC/Tiger och MacBook/i386/Tiger, funkar, men med MacBook/PPC/Leopard eller MacBook/i386/Leopard så kommer inte sista raden fram. (MacBook/PPC betyder alltså PPC-kod körd på MacBook.)

1
Bevaka tråden