From: setera AT us DOT ibm DOT com (Craig Setera) Subject: Spawn and binary pipe read hangs in B19 23 Jun 1998 02:21:08 -0700 Message-ID: <5010400024261593000002L032*.cygnus.gnu-win32@MHS> Mime-Version: 1.0 Content-Type: text/plain To: Can anyone look at the attached code and tell me what if anything I'm doing wrong. This is a small (in comparison to the real code) testcase that seems to point to a bug in B19. If compiled to use fork/exec for the child process creation, both processes will run to completion as expected. If, on the other hand, spawn() is used, the child process hangs on the first pipe read and neither process is able to complete. This can be tested by compiling the code with the variable "childCreateMode" set to either FORK_PROCESS or SPAWN_PROCESS and then running "caller.exe". I'm running with B19 on NT (Sergey's May build I believe). Any help would be greatly appreciated. Thanks, Craig ===================== Begin common.c ========================== #include #include #include #include #define FALSE 0 #define TRUE 1 static unsigned char buffer[1024]; void printBytes(FILE *fp, char *leader, char *data, int size) { int i; char ascii[128]; char buffer[128]; char aByte; ascii[0] = '\0'; fprintf(fp, "%s: ", leader); for (i = 0; i < size; i++) { aByte = (char) data[i]; fprintf(fp, "%02X ", aByte); if (isprint(aByte)) { sprintf(buffer, "%c", aByte); strcat(ascii, buffer); } else { strcat(ascii, "."); } if (!((i + 1) % 16)) { fprintf(fp, " %s\n", ascii); fflush(fp); fprintf(fp, "%s: ", leader); ascii[0] = '\0'; } } if (strlen(ascii) > 0) { for (i = 0; i < (16 - strlen(ascii)); i++) { fprintf(fp, " "); } fprintf(fp, " %s\n", ascii); fflush(fp); } } int writeBytes(int fd, int counter, FILE *logFile) { int count = (counter * 10) + 1; int bytes; unsigned char *buf = buffer; int i = 0; for (i = 0; i < count; i++) buffer[i] = (unsigned char) ((i + 1) % 255); buffer[count - 1] = '\0'; fprintf(logFile, "Entering writeBytes... attempting to write %d bytes\n", count); printBytes(logFile, "\twriteBytes: ", buffer, count); while (count > 0) { do { bytes = write(fd, (char*) buf, count); fprintf(logFile, "\tWrote %d bytes\n", bytes); fflush(logFile); } while ((bytes == -1) && ((errno == EAGAIN) || (errno == EINTR))); if (bytes == -1) { fprintf(logFile, "\tWrite error\n"); fflush(logFile); return FALSE; } count -= bytes; buf += bytes; } fprintf(logFile, "Leaving writeBytes\n"); fflush(logFile); } int readBytes(int fd, int counter, FILE *logFile) { int bytes; int count = (counter * 10) + 1; int totalCount = count; unsigned char *buf = buffer; fprintf(logFile, "Entering readBytes... attempting to read %d bytes\n", count); fflush(logFile); while (count > 0) { do { bytes = read(fd, (char*) buf, count); fprintf(logFile, "\tRead %d bytes\n", bytes); fflush(logFile); } while ((bytes == -1) && ((errno == EAGAIN) || (errno == EINTR))); if (bytes == -1) { fprintf(logFile, "\tError reading\n"); fflush(logFile); return FALSE; } if (bytes == 0) { fprintf(logFile, "\tUnexpected EOF\n"); fflush(logFile); return FALSE; } count -= bytes; buf += bytes; } printBytes(logFile, "\treadBytes: ", buffer, totalCount); fprintf(logFile, "Leaving readBytes\n"); fflush(logFile); } ========================== Begin caller.c ======================= #include #include #include #include #include #define PIPE_READ 0 #define PIPE_WRITE 1 #define P_WAIT 0 #define P_NOWAIT 1 #define O_TEXT 0x0100 /* text file */ #define _O_TEXT 0x0100 /* text file */ #define O_BINARY 0x0200 /* binary file */ #define _O_BINARY 0x0200 /* binary file */ #define SPAWN_PROCESS 0 #define FORK_PROCESS 1 int my_read, my_write; int his_read, his_write; int pid; FILE *logFile; /** * Start the process by using fork/exec */ int fork_callee(char *args[]) { pid = fork(); if (pid == 0) { close(my_read); close(my_write); /* Execute the filter. The "_exit" call should never * be reached, unless some strange error condition * exists. */ execvp(args[0], args); _exit(1); } } /** * Start the process by using spawn */ int spawn_callee(char *args[]) { pid = spawnv(P_NOWAIT, args[0], args); return pid; } int main(int argc, char *argv[]) { int i; int pid; int pipe1[2]; int pipe2[2]; char *args[4]; int childCreateMode = FORK_PROCESS; logFile = fopen("caller.log", "wt"); /* * Open two pipes. (Bidirectional communication). */ fprintf(logFile, "Opening pipes\n"); fflush(logFile); if ((pipe(pipe1) == -1) || (pipe(pipe2) == -1)) { fprintf(logFile, "error opening pipes\n"); fflush(logFile); return 0; } my_read = pipe1[PIPE_READ]; my_write = pipe2[PIPE_WRITE]; his_read = pipe2[PIPE_READ]; his_write = pipe1[PIPE_WRITE]; /* Set to binary mode */ setmode(my_read, _O_BINARY); setmode(my_write, _O_BINARY); setmode(his_read, _O_BINARY); setmode(his_write, _O_BINARY); /** * Build the arguments for calling */ for (i = 0; i < 3; i++) args[i] = (char *) malloc(50); strcpy(args[0], "callee.exe"); sprintf(args[1], "%d", his_read); sprintf(args[2], "%d", his_write); args[3] = NULL; fprintf(logFile, "Starting child process\n"); fflush(logFile); /////////////////////////////////////////// // This is the switch that leads to the // problem!!! /////////////////////////////////////////// if (childCreateMode == SPAWN_PROCESS) spawn_callee(args); else fork_callee(args); if (pid == -1) { fprintf(logFile, "unable to run child process\n"); fflush(logFile); return 0; } close(his_read); his_read = -1; close(his_write); his_write = -1; for (i = 1; i < 100; i++) { writeBytes(my_write, i, logFile); readBytes(my_read, i, logFile); } fclose(logFile); return 0; } ============================= Begin callee.c ====================== #include #include #include #include #include #include #include #include #include int _readfd = 0; int _writefd = 0; static unsigned char buffer[1024]; static FILE *logFile; int main (int argc, char *argv[]) { int i; logFile = fopen("callee.log", "wt"); fprintf(logFile, "Getting file descriptors\n"); fflush(logFile); _readfd = atoi(argv[1]); _writefd = atoi(argv[2]); fprintf(logFile, "Got file descriptors\n"); fprintf(logFile, "readfd = %d\n", _readfd); fprintf(logFile, "writefd = %d\n", _writefd); fflush(logFile); for (i = 1; i < 100; i++) { readBytes(_readfd, i, logFile); writeBytes(_writefd, i, logFile); } fclose(logFile); return 0; } ====================== Begin build commands ============= gcc -c common.c gcc -c caller.c gcc -c callee.c gcc -o caller.exe caller.o common.o gcc -o callee.exe callee.o common.o Craig Setera AS/400 Enterprise Java Development IBM Rochester setera AT us DOT ibm DOT com (507) 253-3387 - Tie: 553-3387 - For help on using this list (especially unsubscribing), send a message to "gnu-win32-request AT cygnus DOT com" with one line of text: "help".