Skip to content

Commit 93ea30f

Browse files
committed
Remove pipe mode of operation
This was extra complexity, and created a problem; see #67 In short, librecode forking could cause output from the calling process to be duplicated, as stdio buffers would be flushed when a child process ended, and then flushed again later in the (duplicate) copy in the caller. This is hard to get around nicely. Since there’s little evidence that the multi-process operation was bringing significant benefits, and since a duplicate bug that had not been fixed on the non-pipe code path was recently spotted as well, remove the pipe code path.
1 parent be816fa commit 93ea30f

File tree

6 files changed

+3
-213
lines changed

6 files changed

+3
-213
lines changed

bootstrap.conf

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# bootstrap.conf (Recode) version 2023-02-11
1+
# bootstrap.conf (Recode) version 2025-03-25
22

33
# This file is part of Recode.
44
#
@@ -65,7 +65,6 @@ gnulib_modules='
6565
minmax
6666
mkstemps
6767
pathmax
68-
pipe-posix
6968
quotearg
7069
sigaction
7170
strndup

doc/recode.texi

Lines changed: 2 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,6 @@ How to use this program
123123
* Listings:: Asking for various lists
124124
* Recoding:: Controlling how files are recoded
125125
* Reversibility:: Reversibility issues
126-
* Sequencing:: Selecting sequencing methods
127126
* Mixed:: Using mixed charset input
128127
* Emacs:: Using Recode within Emacs
129128
* Debugging:: Debugging considerations
@@ -548,7 +547,6 @@ control.
548547
* Listings:: Asking for various lists
549548
* Recoding:: Controlling how files are recoded
550549
* Reversibility:: Reversibility issues
551-
* Sequencing:: Selecting sequencing methods
552550
* Mixed:: Using mixed charset input
553551
* Emacs:: Using Recode within Emacs
554552
* Debugging:: Debugging considerations
@@ -1209,7 +1207,7 @@ requests offers a finer control, @pxref{Requests}).
12091207
@var{charset} may be abbreviated to any unambiguous prefix.
12101208
@end table
12111209

1212-
@node Reversibility, Sequencing, Recoding, Invoking recode
1210+
@node Reversibility, Mixed, Recoding, Invoking recode
12131211
@section Reversibility issues
12141212

12151213
The following options are somewhat related to reversibility issues:
@@ -1411,56 +1409,7 @@ length 3. On the other end, recoding six times in the same direction
14111409
would recover all characters in cycles of length 1, 2, 3 or 6.
14121410
@end enumerate
14131411

1414-
@node Sequencing, Mixed, Reversibility, Invoking recode
1415-
@section Selecting sequencing methods
1416-
1417-
@cindex sequencing
1418-
Recode can split itself into multiple parallel processes when it is
1419-
discovered that many passes are needed to comply with the @var{request}.
1420-
For example, suppose that four elementary steps were selected at
1421-
recoding path optimisation time. Then Recode will split itself into
1422-
four different interconnected tasks, logically equivalent to:
1423-
1424-
@example
1425-
@var{step1} <@var{input} | @var{step2} | @var{step3} | @var{step4} >@var{output}
1426-
@end example
1427-
1428-
On systems where the pipes method is not available, the steps are
1429-
performed in series.
1430-
1431-
@table @samp
1432-
@item --sequence=memory
1433-
@opindex --sequence
1434-
@cindex memory sequencing
1435-
When the recoding requires a combination of two or more elementary
1436-
recoding steps, this option forces many passes over the data, using
1437-
in-memory buffers to hold all intermediate results.
1438-
If this option is selected in filter
1439-
mode, that is, when the program reads standard input and writes standard
1440-
output, it might take longer for programs further down the pipe chain to
1441-
start receiving some recoded data.
1442-
1443-
@item -p
1444-
@itemx --sequence=pipe
1445-
@opindex -p
1446-
@cindex pipe sequencing
1447-
When the recoding requires a combination of two or more elementary
1448-
recoding steps, this option forces the program to fork itself into a few
1449-
copies interconnected with pipes, using the @code{pipe(2)} system call.
1450-
All copies of the program operate in parallel. This is the default
1451-
behaviour in filter mode. If this option is used when files are recoded
1452-
over themselves, this should also save disk space because some temporary
1453-
files might not be needed, at the cost of more system overhead.
1454-
1455-
@item -i
1456-
@itemx --sequence=files
1457-
@opindex -i
1458-
@cindex file sequencing
1459-
This option is accepted for backwards compatibility, and acts like
1460-
@samp{--sequence=memory}.
1461-
@end table
1462-
1463-
@node Mixed, Emacs, Sequencing, Invoking recode
1412+
@node Mixed, Emacs, Reversibility, Invoking recode
14641413
@section Using mixed charset input
14651414

14661415
In real life and practice, textual files are often made up of many charsets

lib/.gitignore

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,6 @@
8282
/msvc-nothrow.c
8383
/msvc-nothrow.h
8484
/pathmax.h
85-
/pipe.c
8685
/printf-args.c
8786
/printf-args.h
8887
/printf-frexp.c

m4/.gitignore

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,6 @@ gnulib-comp.m4
5252
/nocrash.m4
5353
/off_t.m4
5454
/pathmax.m4
55-
/pipe.m4
5655
/printf-frexp.m4
5756
/printf-frexpl.m4
5857
/printf.m4

src/main.c

Lines changed: 0 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -133,35 +133,6 @@ task_perror (RECODE_CONST_TASK task)
133133
return _("Internal recoding bug");
134134
}
135135
}
136-
137-
/*-----------------.
138-
| Signal handler. |
139-
`-----------------*/
140-
141-
#ifdef HAVE_PIPE
142-
static void
143-
sig_catch(int sig, void (*handler) (int))
144-
{
145-
struct sigaction sa;
146-
sa.sa_handler = handler;
147-
sa.sa_flags = 0;
148-
sigemptyset (&sa.sa_mask);
149-
sigaction (sig, &sa, NULL); /* ignore error: none possible */
150-
}
151-
152-
static void
153-
signal_handler (int number)
154-
{
155-
recode_interrupted = 1;
156-
sig_catch (number, signal_handler);
157-
}
158-
159-
static void
160-
setup_signals (void)
161-
{
162-
sig_catch (SIGPIPE, signal_handler);
163-
}
164-
#endif
165136

166137
/* Main control. */
167138

@@ -777,10 +748,6 @@ warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"),
777748
/* Discard the request argument. */
778749
optind++;
779750

780-
#if HAVE_PIPE
781-
setup_signals ();
782-
#endif
783-
784751
{
785752
RECODE_TASK task;
786753

src/task.c

Lines changed: 0 additions & 123 deletions
Original file line numberDiff line numberDiff line change
@@ -232,11 +232,6 @@ recode_perform_task (RECODE_TASK task)
232232
struct recode_subtask subtask_block;
233233
RECODE_SUBTASK subtask = &subtask_block;
234234

235-
#if HAVE_PIPE
236-
int pipe_pair[2]; /* pair of file descriptors for a pipe */
237-
pid_t wait_status; /* status returned by wait() */
238-
#endif
239-
240235
struct recode_read_write_text input;
241236
struct recode_read_write_text output;
242237
memset (&input, 0, sizeof (struct recode_read_write_text));
@@ -298,71 +293,6 @@ recode_perform_task (RECODE_TASK task)
298293
{
299294
subtask->output = output;
300295
subtask->output.cursor = subtask->output.buffer;
301-
302-
#if HAVE_PIPE
303-
/* Create all subprocesses, from the first to the last, and
304-
interconnect them. */
305-
306-
if (pipe (pipe_pair) < 0)
307-
{
308-
recode_perror (NULL, "pipe ()");
309-
recode_if_nogo (RECODE_SYSTEM_ERROR, subtask);
310-
SUBTASK_RETURN (subtask);
311-
}
312-
xset_binary_mode (pipe_pair[0], O_BINARY);
313-
xset_binary_mode (pipe_pair[1], O_BINARY);
314-
if (child_process = fork (), child_process < 0)
315-
{
316-
recode_perror (NULL, "fork ()");
317-
recode_if_nogo (RECODE_SYSTEM_ERROR, subtask);
318-
SUBTASK_RETURN (subtask);
319-
}
320-
if (child_process == 0)
321-
{
322-
/* The child executes its recoding step, reading from the
323-
current input file and writing to the pipe; then it exits. */
324-
325-
if (close (pipe_pair[0]) < 0)
326-
{
327-
recode_perror (NULL, "close ()");
328-
recode_if_nogo (RECODE_SYSTEM_ERROR, subtask);
329-
}
330-
if (subtask->output.file = fdopen (pipe_pair[1], "w"),
331-
subtask->output.file == NULL)
332-
{
333-
recode_perror (NULL, "fdopen ()");
334-
recode_if_nogo (RECODE_SYSTEM_ERROR, subtask);
335-
}
336-
}
337-
else
338-
{
339-
/* The parent saves the read end of the pipe for the next step. */
340-
341-
if (input.file = fdopen (pipe_pair[0], "r"),
342-
input.file == NULL)
343-
{
344-
recode_perror (NULL, "fdopen ()");
345-
recode_if_nogo (RECODE_SYSTEM_ERROR, subtask);
346-
close (pipe_pair[0]);
347-
close (pipe_pair[1]);
348-
SUBTASK_RETURN (subtask);
349-
}
350-
if (close (pipe_pair[1]) < 0)
351-
{
352-
recode_perror (NULL, "close ()");
353-
recode_if_nogo (RECODE_SYSTEM_ERROR, subtask);
354-
close (pipe_pair[0]);
355-
fclose (input.file);
356-
SUBTASK_RETURN (subtask);
357-
}
358-
359-
/* Close the input file when we opened it. */
360-
361-
if (subtask->input.file && subtask->input.name &&
362-
subtask->input.name[0])
363-
fclose (subtask->input.file);
364-
}
365-
#endif
366296
}
367297
else
368298
{
@@ -395,9 +325,6 @@ recode_perform_task (RECODE_TASK task)
395325
subtask->step = request->sequence_array + sequence_index;
396326
(*subtask->step->transform_routine) (subtask);
397327

398-
#if HAVE_PIPE
399-
break; /* child/top-level process: escape from loop */
400-
#else
401328
/* Post-step clean up for memory sequence. */
402329

403330
if (subtask->input.file)
@@ -422,7 +349,6 @@ recode_perform_task (RECODE_TASK task)
422349
output = input;
423350
input = subtask->output;
424351
}
425-
#endif
426352
}
427353

428354
if (sequence_index + 1 == (unsigned)request->sequence_length)
@@ -444,57 +370,8 @@ recode_perform_task (RECODE_TASK task)
444370
recode_if_nogo (RECODE_SYSTEM_ERROR, subtask);
445371
}
446372

447-
#if HAVE_PIPE
448-
/* Child process exits here. */
449-
450-
if (child_process == 0)
451-
exit (task->error_so_far < task->fail_level ? EXIT_SUCCESS
452-
: EXIT_FAILURE);
453-
else
454-
{
455-
/* Wait on all children, mainly to avoid synchronisation problems on
456-
output file contents, but also to reduce the number of zombie
457-
processes in case the user recodes many files at once. */
458-
459-
while (wait (&wait_status) > 0)
460-
{
461-
/* Diagnose and abort on any abnormally terminating child. */
462-
463-
if (!(WIFEXITED (wait_status)
464-
|| (WIFSIGNALED (wait_status)
465-
&& WTERMSIG (wait_status) == SIGPIPE)))
466-
{
467-
recode_error (NULL, _("Child process wait status is 0x%0.2x"),
468-
wait_status);
469-
recode_if_nogo (RECODE_SYSTEM_ERROR, subtask);
470-
SUBTASK_RETURN (subtask);
471-
}
472-
473-
/* Check for a nonzero exit from the terminating child. */
474-
475-
if (WIFEXITED (wait_status)
476-
? WEXITSTATUS (wait_status) != 0
477-
: WTERMSIG (wait_status) != 0)
478-
/* FIXME: It is not very clear what happened in sub-processes. */
479-
if (task->error_so_far < task->fail_level)
480-
{
481-
task->error_so_far = task->fail_level;
482-
task->error_at_step = request->sequence_array + (unsigned)request->sequence_length - 1;
483-
}
484-
}
485-
486-
if (recode_interrupted)
487-
/* FIXME: It is not very clear what happened in sub-processes. */
488-
if (task->error_so_far < task->fail_level)
489-
{
490-
task->error_so_far = task->fail_level;
491-
task->error_at_step = request->sequence_array + (unsigned)request->sequence_length - 1;
492-
}
493-
}
494-
#else
495373
free (input.buffer);
496374
free (output.buffer);
497-
#endif
498375

499376
task->output = subtask->output;
500377
SUBTASK_RETURN (subtask);

0 commit comments

Comments
 (0)