IonicWind Software

Aurora Compiler => General Discussion => Topic started by: Parker on May 27, 2006, 02:20:28 PM

Title: ERROR_BROKEN_PIPE
Post by: Parker on May 27, 2006, 02:20:28 PM
What could be causing that error? The code I'm using is this:
struct PROCESS_T
{
CommanderWnd *commander;
unsigned int hReadOut;
PROCESS_INFORMATION pi;
}

global sub DoCommand( CommanderWnd *commander, string command )
{
Dim si As STARTUPINFO;
Dim pi As PROCESS_INFORMATION;
Dim sa As SECURITY_ATTRIBUTES;
Dim hReadPipe=0 As unsigned int;
Dim hWritePipe=0 As unsigned int;
Dim bytesRead=0 As Int;
Dim result=0 As Int;
Dim totalBytes=0 As Int;
commander->ClearOutput( );
commander->SendOutputString( "Doing command\n" );

RtlZeroMemory( si, sizeof( STARTUPINFO ) );
RtlZeroMemory( pi, sizeof( PROCESS_INFORMATION ) );
RtlZeroMemory( sa, sizeof( SECURITY_ATTRIBUTES ) );

sa.nLength = Len(SECURITY_ATTRIBUTES);
sa.bInheritHandle = 1;

If CreatePipe(hReadPipe, hWritePipe, sa, 0) = 0
{
commander->SendOutputString( "Failed to create pipe..." );
Return;
}

si.cb = Len(STARTUPINFO);
si.dwFlags = 25 | 1;//STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW;
si.hStdOutput = hWritePipe;
si.hStdError = hWritePipe;
si.wShowWindow = 0;

If CreateProcess(0, command, sa, sa, 1, 0x00000020/*NORMAL_PRIORITY_CLASS*/, 0, 0, si, pi) = 0
{
commander->SendOutputString( "Failed to open..." );
Return;
}

CloseHandle( hWritePipe );

//TODO: Start a thread of PipeProc
PROCESS_T *pp;
pp = new( PROCESS_T, 1 );
pp->commander = commander;
pp->hReadOut = hReadPipe;
pp->pi = pi;

ThreadStart( &PipeProc, pp );
}

sub PipeProc( PROCESS_T *p )
{
Dim sBuffer[1024] As DString;
int bytesRead=0;
int totalBytes=0;
int result;
RtlZeroMemory( sBuffer, 1024 );

Do{
result = ReadFile(p->hReadOut, &sBuffer, 1024, &bytesRead, 0);
if( !result ) p->commander->SendOutputString( numtostr( GetLastError( ) ) );
p->commander->SendOutputString( strLeft(sBuffer, bytesRead) );
totalBytes += bytesRead;
}Until !result;
p->commander->SendOutputString( sprint( "\nRead ", totalBytes, " bytes" ) );

CloseHandle( p->pi.hProcess );
CloseHandle( p->pi.hThread );
CloseHandle( p->hReadOut );
}


Hmm, and the Aurora console version works fine ???
struct PROCESS_T
{
unsigned int hReadOut;
PROCESS_INFORMATION pi;
}

global sub DoCommand( string command )
{
Dim si As STARTUPINFO;
Dim pi As PROCESS_INFORMATION;
Dim sa As SECURITY_ATTRIBUTES;
Dim hReadPipe=0 As unsigned int;
Dim hWritePipe=0 As unsigned int;

print( "Doing command" );

RtlZeroMemory( si, sizeof( STARTUPINFO ) );
RtlZeroMemory( pi, sizeof( PROCESS_INFORMATION ) );
RtlZeroMemory( sa, sizeof( SECURITY_ATTRIBUTES ) );

sa.nLength = Len(SECURITY_ATTRIBUTES);
sa.bInheritHandle = 1;

If CreatePipe(hReadPipe, hWritePipe, sa, 0) = 0
{
print( "Failed to create pipe..." );
Return;
}

si.cb = Len(STARTUPINFO);
si.dwFlags = 25 | 1;//STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW;
si.hStdOutput = hWritePipe;
si.hStdError = hWritePipe;
si.wShowWindow = 0;

If CreateProcess(0, command, sa, sa, 1, 0x00000020/*NORMAL_PRIORITY_CLASS*/, 0, 0, si, pi) = 0
{
print( "Failed to open..." );
Return;
}

CloseHandle( hWritePipe );

//TODO: Start a thread of PipeProc
PROCESS_T *pp;
pp = new( PROCESS_T, 1 );
pp->hReadOut = hReadPipe;
pp->pi = pi;

ThreadStart( &PipeProc, pp );
}

sub PipeProc( PROCESS_T *p )
{
Dim sBuffer[1024] As DString;
int bytesRead=0;
int totalBytes=0;
int result;
RtlZeroMemory( sBuffer, 1024 );

Do{
result = ReadFile(p->hReadOut, &sBuffer, 1024, &bytesRead, 0);
if( !result ) print( "\n\nError: ", GetLastError( ) );
print( strLeft(sBuffer, bytesRead) );
totalBytes += bytesRead;
}Until !result;
print( "\nRead ", totalBytes, " bytes" );

CloseHandle( p->pi.hProcess );
CloseHandle( p->pi.hThread );
CloseHandle( p->hReadOut );
delete p;
}

global sub main( )
{
string command;
print(">> ",);
command=readln( );
DoCommand(command);
}
Title: Re: ERROR_BROKEN_PIPE
Post by: Ionic Wind Support Team on May 27, 2006, 02:53:14 PM
Windows programs don't get assigned stdio handles by the OS.  If you use the code I presented in the developers area you shouldn't have any problems.  You need the process atrributes from the running parent (assuming your IDE) assigned to the pipe or no data will flow.  Hence the DuplicateHandle calls.

In a console program Windows assigns stdio handles to the parent process and they will be shared by any pipes you create. 

Title: Re: ERROR_BROKEN_PIPE
Post by: Parker on May 27, 2006, 03:07:51 PM
Okay, thanks. I thought I could make the conversion easier on myself by converting a simple console program, but I guess not ;)