fflush() all stdio buffers before calling fork(). End child processes with _exit() instead of exit() to avoid double fflushing in parent i/o streams

This commit is contained in:
stefan schippers 2023-01-19 02:46:45 +01:00
parent 49135f3f2e
commit 6f6bd65035
5 changed files with 50 additions and 22 deletions

View File

@ -223,6 +223,7 @@
</ItemDefinitionGroup> </ItemDefinitionGroup>
<ItemGroup> <ItemGroup>
<ClCompile Include="..\src\actions.c" /> <ClCompile Include="..\src\actions.c" />
<ClCompile Include="..\src\cairo_jpg.c" />
<ClCompile Include="..\src\callback.c" /> <ClCompile Include="..\src\callback.c" />
<ClCompile Include="..\src\check.c" /> <ClCompile Include="..\src\check.c" />
<ClCompile Include="..\src\clip.c" /> <ClCompile Include="..\src\clip.c" />
@ -257,6 +258,7 @@
<ClCompile Include="parselabel.c" /> <ClCompile Include="parselabel.c" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClInclude Include="..\src\cairo_jpg.h" />
<ClInclude Include="..\src\xschem.h" /> <ClInclude Include="..\src\xschem.h" />
<ClInclude Include="config.h" /> <ClInclude Include="config.h" />
<ClInclude Include="expandlabel.h" /> <ClInclude Include="expandlabel.h" />

View File

@ -273,16 +273,16 @@ void new_xschem_process(const char *cell, int symbol)
fprintf(errfp, "new_xschem_process(): executable not found\n"); fprintf(errfp, "new_xschem_process(): executable not found\n");
return; return;
} }
fflush(NULL); /* flush all stdio streams before process forking */
/* double fork method to avoid zombies 20180925*/ /* double fork method to avoid zombies 20180925*/
if ( (pid1 = fork()) ) { if ( (pid1 = fork()) > 0 ) {
/* parent process */ /* parent process */
waitpid(pid1, &status, 0); waitpid(pid1, &status, 0);
} else if (!pid1) { } else if (pid1 == 0) {
/* child process */ /* child process */
if ( (pid2 = fork()) ) { if ( (pid2 = fork()) > 0 ) {
exit(0); /* --> child of child will be reparented to init */ _exit(0); /* --> child of child will be reparented to init */
} else if (!pid2) { } else if (pid2 == 0) {
/* child of child */ /* child of child */
if(!cell || !cell[0]) { if(!cell || !cell[0]) {
if(!symbol) if(!symbol)
@ -303,7 +303,7 @@ void new_xschem_process(const char *cell, int symbol)
} else { } else {
/* error */ /* error */
fprintf(errfp, "new_xschem_process(): fork error 1\n"); fprintf(errfp, "new_xschem_process(): fork error 1\n");
tcleval("exit"); _exit(1);
} }
} else { } else {
/* error */ /* error */

View File

@ -142,22 +142,23 @@ void ps_drawPNG(xRect* r, double x1, double y1, double x2, double y2, int rot, i
size_t fileSize = 0; size_t fileSize = 0;
int quality=100; int quality=100;
const char *quality_attr; const char *quality_attr;
size_t image_data_len;
quality_attr = get_tok_value(r->prop_ptr, "jpeg_quality", 0); quality_attr = get_tok_value(r->prop_ptr, "jpeg_quality", 0);
if(quality_attr[0]) quality = atoi(quality_attr); if(quality_attr[0]) quality = atoi(quality_attr);
my_strdup(59, &filter, get_tok_value(r->prop_ptr, "filter", 0)); my_strdup(59, &filter, get_tok_value(r->prop_ptr, "filter", 0));
my_strdup2(1183, &image_data64_ptr, get_tok_value(r->prop_ptr, "image_data", 0)); image_data_len = my_strdup2(1183, &image_data64_ptr, get_tok_value(r->prop_ptr, "image_data", 0));
if (filter) { if (filter) {
size_t filtersize = 0; size_t filtersize = 0;
char* filterdata = NULL; char* filterdata = NULL;
closure.buffer = NULL; closure.buffer = NULL;
filterdata = (char*)base64_decode(image_data64_ptr, strlen(image_data64_ptr), &filtersize); filterdata = (char*)base64_decode(image_data64_ptr, image_data_len, &filtersize);
filter_data(filterdata, filtersize, (char**)&closure.buffer, &data_size, filter); filter_data(filterdata, filtersize, (char**)&closure.buffer, &data_size, filter);
my_free(1661, &filterdata); my_free(1661, &filterdata);
} }
else { else {
closure.buffer = base64_decode(image_data64_ptr, strlen(image_data64_ptr), &data_size); closure.buffer = base64_decode(image_data64_ptr, image_data_len, &data_size);
} }
my_free(1664, &filter); my_free(1664, &filter);
my_free(1184, &image_data64_ptr); my_free(1184, &image_data64_ptr);
@ -220,7 +221,6 @@ void ps_drawPNG(xRect* r, double x1, double y1, double x2, double y2, int rot, i
if(rot==2) fprintf(fd, "180 rotate\n"); if(rot==2) fprintf(fd, "180 rotate\n");
if(rot==3) fprintf(fd, "270 rotate\n"); if(rot==3) fprintf(fd, "270 rotate\n");
fprintf(fd, "%g %g scale\n", (X_TO_PS(x2) - X_TO_PS(x1))*0.97, (Y_TO_PS(y2) - Y_TO_PS(y1))*0.97); fprintf(fd, "%g %g scale\n", (X_TO_PS(x2) - X_TO_PS(x1))*0.97, (Y_TO_PS(y2) - Y_TO_PS(y1))*0.97);
fprintf(fd, "%g\n", (double)png_size_x); fprintf(fd, "%g\n", (double)png_size_x);
fprintf(fd, "%g\n", (double)png_size_y); fprintf(fd, "%g\n", (double)png_size_y);
fprintf(fd, "8\n"); fprintf(fd, "8\n");

View File

@ -64,7 +64,7 @@ int filter_data(const char *din, const size_t ilen,
{ {
int p1[2]; /* parent -> child, 0: read, 1: write */ int p1[2]; /* parent -> child, 0: read, 1: write */
int p2[2]; /* child -> parent, 0: read, 1: write */ int p2[2]; /* child -> parent, 0: read, 1: write */
int ret = 0; int ret = 0, wstatus;
pid_t pid; pid_t pid;
size_t bufsize = 32768, oalloc = 0, n = 0; size_t bufsize = 32768, oalloc = 0, n = 0;
@ -77,6 +77,13 @@ int filter_data(const char *din, const size_t ilen,
dbg(1, "filter_data(): ilen=%ld, cmd=%s\n", ilen, cmd); dbg(1, "filter_data(): ilen=%ld, cmd=%s\n", ilen, cmd);
pipe(p1); pipe(p1);
pipe(p2); pipe(p2);
dbg(1, "p1[0] = %d\n", p1[0]);
dbg(1, "p1[1] = %d\n", p1[1]);
dbg(1, "p2[0] = %d\n", p2[0]);
dbg(1, "p2[1] = %d\n", p2[1]);
signal(SIGPIPE, SIG_IGN); /* so attempting write/read a broken pipe won't kill program */ signal(SIGPIPE, SIG_IGN); /* so attempting write/read a broken pipe won't kill program */
/* /*
* p2 * p2
@ -85,26 +92,39 @@ int filter_data(const char *din, const size_t ilen,
* ------------------- p1[1] ---------> p1[0] ------------------- * ------------------- p1[1] ---------> p1[0] -------------------
* p1 * p1
*/ */
fflush(NULL); /* flush all stdio streams before process forking */
if( (pid = fork()) == 0) { if( (pid = fork()) == 0) {
#if 1
char **av; char **av;
int ac; int ac;
#endif
/* child */ /* child */
close(p1[1]); /* only read from p1 */ close(p1[1]); /* only read from p1 */
close(p2[0]); /* only write to p2 */ close(p2[0]); /* only write to p2 */
close(0); /* dup2(p1[0],0); */ /* connect read side of read pipe to stdin */ close(0); /* dup2(p1[0],0); */ /* connect read side of read pipe to stdin */
dup(p1[0]); dup(p1[0]);
close(p1[0]);
close(1); /* dup2(p2[1],1); */ /* connect write side of write pipe to stdout */ close(1); /* dup2(p2[1],1); */ /* connect write side of write pipe to stdout */
dup(p2[1]); dup(p2[1]);
close(p2[1]);
#if 1
av = parse_cmd_string(cmd, &ac); av = parse_cmd_string(cmd, &ac);
if(execvp(av[0], av) == -1) { if(execvp(av[0], av) == -1) {
#endif
#if 0
if(execl("/bin/sh", "sh", "-c", cmd, (char *) NULL) == -1) {
#endif
#if 0
if(system(cmd) == -1) {
#endif
fprintf(stderr, "error: conversion failed\n"); fprintf(stderr, "error: conversion failed\n");
close(p1[0]);
close(p2[1]);
ret = 1; ret = 1;
} }
exit(ret); _exit(ret);
} }
/* parent */ /* parent */
close(p1[0]); /*only write to p1 */ close(p1[0]); /*only write to p1 */
@ -139,9 +159,13 @@ int filter_data(const char *din, const size_t ilen,
fprintf(stderr, "no data read\n"); fprintf(stderr, "no data read\n");
ret = 1; ret = 1;
} }
waitpid(pid, NULL, 0); /* write for child process to finish and unzombie it */ waitpid(pid, &wstatus, 0); /* write for child process to finish and unzombie it */
close(p2[0]); close(p2[0]);
signal(SIGPIPE, SIG_DFL); /* restore default SIGPIPE signal action */ signal(SIGPIPE, SIG_DFL); /* restore default SIGPIPE signal action */
if(WIFEXITED(wstatus)) dbg(1, "Child exited normally\n");
dbg(1, "Child exit status=%d\n", WEXITSTATUS(wstatus));
if(WIFSIGNALED(wstatus))dbg(1, "Child was terminated by signal\n");
return ret; return ret;
} }
#else /* anyone wanting to write a similar function for windows Welcome! */ #else /* anyone wanting to write a similar function for windows Welcome! */
@ -2391,12 +2415,13 @@ void push_undo(void)
#elif HAS_PIPE==1 #elif HAS_PIPE==1
my_snprintf(diff_name, S(diff_name), "%s/undo%d", xctx->undo_dirname, xctx->cur_undo_ptr%MAX_UNDO); my_snprintf(diff_name, S(diff_name), "%s/undo%d", xctx->undo_dirname, xctx->cur_undo_ptr%MAX_UNDO);
pipe(pd); pipe(pd);
fflush(NULL); /* flush all stdio streams before process forking */
if((pid = fork()) ==0) { /* child process */ if((pid = fork()) ==0) { /* child process */
close(pd[1]); /* close write side of pipe */ close(pd[1]); /* close write side of pipe */
if(!(diff_fd=freopen(diff_name,"w", stdout))) /* redirect stdout to file diff_name */ if(!(diff_fd=freopen(diff_name,"w", stdout))) /* redirect stdout to file diff_name */
{ {
dbg(1, "push_undo(): problems opening file %s \n",diff_name); dbg(1, "push_undo(): problems opening file %s \n",diff_name);
tcleval("exit"); _exit(1);
} }
/* the following 2 statements are a replacement for dup2() which is not c89 /* the following 2 statements are a replacement for dup2() which is not c89
@ -2411,7 +2436,7 @@ void push_undo(void)
execlp("gzip", "gzip", "--fast", "-c", NULL); /* replace current process with comand */ execlp("gzip", "gzip", "--fast", "-c", NULL); /* replace current process with comand */
/* never gets here */ /* never gets here */
fprintf(errfp, "push_undo(): problems with execlp\n"); fprintf(errfp, "push_undo(): problems with execlp\n");
tcleval("exit"); _exit(1);
} }
close(pd[0]); /* close read side of pipe */ close(pd[0]); /* close read side of pipe */
fd=fdopen(pd[1],"w"); fd=fdopen(pd[1],"w");
@ -2491,12 +2516,13 @@ void pop_undo(int redo, int set_modify_status)
#elif HAS_PIPE==1 #elif HAS_PIPE==1
my_snprintf(diff_name, S(diff_name), "%s/undo%d", xctx->undo_dirname, xctx->cur_undo_ptr%MAX_UNDO); my_snprintf(diff_name, S(diff_name), "%s/undo%d", xctx->undo_dirname, xctx->cur_undo_ptr%MAX_UNDO);
pipe(pd); pipe(pd);
fflush(NULL); /* flush all stdio streams before process forking */
if((pid = fork())==0) { /* child process */ if((pid = fork())==0) { /* child process */
close(pd[0]); /* close read side of pipe */ close(pd[0]); /* close read side of pipe */
if(!(diff_fd=freopen(diff_name,"r", stdin))) /* redirect stdin from file name */ if(!(diff_fd=freopen(diff_name,"r", stdin))) /* redirect stdin from file name */
{ {
dbg(1, "pop_undo(): problems opening file %s \n",diff_name); dbg(1, "pop_undo(): problems opening file %s \n",diff_name);
tcleval("exit"); _exit(1);
} }
/* connect write side of pipe to stdout */ /* connect write side of pipe to stdout */
#if HAS_DUP2 #if HAS_DUP2
@ -2508,7 +2534,7 @@ void pop_undo(int redo, int set_modify_status)
execlp("gzip", "gzip", "-d", "-c", NULL); /* replace current process with command */ execlp("gzip", "gzip", "-d", "-c", NULL); /* replace current process with command */
/* never gets here */ /* never gets here */
dbg(1, "pop_undo(): problems with execlp\n"); dbg(1, "pop_undo(): problems with execlp\n");
tcleval("exit"); _exit(1);
} }
close(pd[1]); /* close write side of pipe */ close(pd[1]); /* close write side of pipe */
fd=fdopen(pd[0],"r"); fd=fdopen(pd[0],"r");

View File

@ -1077,7 +1077,6 @@ extern Xschem_ctx *xctx;
extern void draw_image(int dr, xRect *r, double *x1, double *y1, double *x2, double *y2, int rot, int flip); extern void draw_image(int dr, xRect *r, double *x1, double *y1, double *x2, double *y2, int rot, int flip);
extern int filter_data(const char *din, const size_t ilen, extern int filter_data(const char *din, const size_t ilen,
char **dout, size_t *olen, const char *cmd); char **dout, size_t *olen, const char *cmd);
extern cairo_status_t png_reader(void* in_closure, unsigned char* out_data, unsigned int length);
extern int embed_rawfile(const char *rawfile); extern int embed_rawfile(const char *rawfile);
extern int read_rawfile_from_attr(const char *b64s, size_t length, const char *type); extern int read_rawfile_from_attr(const char *b64s, size_t length, const char *type);
extern int raw_read_from_attr(const char *type); extern int raw_read_from_attr(const char *type);
@ -1170,6 +1169,7 @@ extern void hash_wire(int what, int n, int incremental);
extern void hash_instances(void); /* 20171203 insert instance bbox in spatial hash table */ extern void hash_instances(void); /* 20171203 insert instance bbox in spatial hash table */
#if HAS_CAIRO==1 #if HAS_CAIRO==1
extern cairo_status_t png_reader(void* in_closure, unsigned char* out_data, unsigned int length);
extern int text_bbox_nocairo(const char * str,double xscale, double yscale, extern int text_bbox_nocairo(const char * str,double xscale, double yscale,
short rot, short flip, int hcenter, int vcenter, short rot, short flip, int hcenter, int vcenter,
double x1,double y1, double *rx1, double *ry1, double x1,double y1, double *rx1, double *ry1,