How to redirect error but not output and keep text written to console in the right order? (F#)
I have two programs that I am running, one of which is run as a child process by the other. When the child process writes to stderr, I want to capture that in the parent process so I can tell if there was an error, and then log the error message to the console just like the child process tried to do.
The problem is that the child process writes several lines of text to stdout immediately after writing to stderr. When the parent process intercepts stderr messages and logs them itself, they get written in parallel with the stdout messages and the text appears in the wrong order.
I have created two F# scripts as a minimal reproduction of this problem. This is the script for the child process:
open System
let logError (x : string) : unit =
Console.ForegroundColor <- ConsoleColor.Red
try stderr.WriteLine x
finally Console.ResetColor ()
let logWarning (x : string) : unit =
Console.ForegroundColor <- ConsoleColor.Yellow
try stdout.WriteLine x
finally Console.ResetColor ()
let logInfo (x : string) : unit =
Console.ForegroundColor <- ConsoleColor.Green
try stdout.WriteLine x
finally Console.ResetColor ()
logError "The quick brown fox jumps over the lazy dog."
logWarning "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc eu est ut arcu finibus iaculis. Maecenas dapibus luctus convallis. Donec tristique accumsan ante sit amet maximus. Sed molestie eros sit amet pretium rhoncus. Sed odio lectus, vestibulum vitae consequat sit amet, eleifend ac augue. Vivamus eros quam, lobortis eget consequat in, pulvinar vel dolor. Sed efficitur fermentum purus eu imperdiet. Mauris posuere, metus nec fringilla accumsan, massa nisi egestas augue, et tristique ligula dolor sit amet nibh. Proin ultricies fermentum tellus, vitae porttitor mauris elementum id. Donec arcu dolor, posuere vel efficitur ultrices, sollicitudin sit amet mauris. Sed eu suscipit leo, in vehicula sem. Morbi congue nibh vitae orci lobortis, gravida volutpat augue imperdiet. Phasellus fringilla arcu ac tellus porttitor mattis. Donec in ante vitae sem varius pulvinar."
logInfo "Nam lorem justo, laoreet ac convallis et, semper et leo. Fusce ornare, risus ut porta tristique, purus lacus ultricies ante, ac semper metus eros quis sapien. Nunc vulputate neque ut efficitur condimentum. Quisque facilisis lacus at lorem condimentum suscipit. Aenean volutpat et dui non pharetra. Pellentesque pretium euismod sollicitudin. Phasellus ullamcorper nulla quis nibh tincidunt consectetur. Nulla gravida finibus mi, sed elementum ligula maximus sed. Ut eu dignissim ex. Nullam vestibulum accumsan ex, ut facilisis elit facilisis scelerisque. Integer pellentesque, sem a molestie porta, tortor felis consectetur lorem, ut interdum lacus mauris vel nisi. Maecenas justo nulla, pharetra at malesuada ac, sollicitudin quis tortor. Integer vehicula, mauris ac tristique vehicula, leo nibh cursus sem, sed rhoncus libero sapien ac tellus."
And this is the script for the parent process:
open System
open System.Diagnostics
let handleErr (args : DataReceivedEventArgs) : unit =
Console.ForegroundColor <- ConsoleColor.Red
try stderr.WriteLine args.Data
finally Console.ResetColor ()
let p = new Process ()
p.StartInfo.FileName <- "fsi"
p.StartInfo.Arguments <- "child.fsx"
p.StartInfo.UseShellExecute <- false
p.StartInfo.RedirectStandardError <- true
p.ErrorDataReceived.Add handleErr
p.Start ()
p.BeginErrorReadLine ()
p.WaitForExit ()
The expected output of the child process would be a line in red, followed by a paragraph in yellow, and finally a paragraph in green. When I run the child process on its own that is what gets output. But when I run it through the parent process this happens:
You can see that the error message "The quick brown fox jumped over the lazy dog." printed in the middle of the paragraph that should have printed after it, and the foreground color is incorrect. I have tried to find a solution for this and failed so far, as none of the following things will work:
- Use locks to allow only one function to print to the console at once - This won't help because the functions are isolated across different processes, not just different threads.
- Redirect stdout as well as stderr - This makes it impossible to preserve the color of the messages written to stdout.
- Combine stderr with stdout - I need a way to distinguish between stderr and stdout, so that the parent process can tell if stderr has been written to.
Is there a way in the parent process that I can detect whether the child process has written to stderr, while not redirecting the stderr stream and still letting the child process handle logging to the console?
.net f# system.diagnostics processstartinfo redirectstandardoutput
|
show 1 more comment
I have two programs that I am running, one of which is run as a child process by the other. When the child process writes to stderr, I want to capture that in the parent process so I can tell if there was an error, and then log the error message to the console just like the child process tried to do.
The problem is that the child process writes several lines of text to stdout immediately after writing to stderr. When the parent process intercepts stderr messages and logs them itself, they get written in parallel with the stdout messages and the text appears in the wrong order.
I have created two F# scripts as a minimal reproduction of this problem. This is the script for the child process:
open System
let logError (x : string) : unit =
Console.ForegroundColor <- ConsoleColor.Red
try stderr.WriteLine x
finally Console.ResetColor ()
let logWarning (x : string) : unit =
Console.ForegroundColor <- ConsoleColor.Yellow
try stdout.WriteLine x
finally Console.ResetColor ()
let logInfo (x : string) : unit =
Console.ForegroundColor <- ConsoleColor.Green
try stdout.WriteLine x
finally Console.ResetColor ()
logError "The quick brown fox jumps over the lazy dog."
logWarning "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc eu est ut arcu finibus iaculis. Maecenas dapibus luctus convallis. Donec tristique accumsan ante sit amet maximus. Sed molestie eros sit amet pretium rhoncus. Sed odio lectus, vestibulum vitae consequat sit amet, eleifend ac augue. Vivamus eros quam, lobortis eget consequat in, pulvinar vel dolor. Sed efficitur fermentum purus eu imperdiet. Mauris posuere, metus nec fringilla accumsan, massa nisi egestas augue, et tristique ligula dolor sit amet nibh. Proin ultricies fermentum tellus, vitae porttitor mauris elementum id. Donec arcu dolor, posuere vel efficitur ultrices, sollicitudin sit amet mauris. Sed eu suscipit leo, in vehicula sem. Morbi congue nibh vitae orci lobortis, gravida volutpat augue imperdiet. Phasellus fringilla arcu ac tellus porttitor mattis. Donec in ante vitae sem varius pulvinar."
logInfo "Nam lorem justo, laoreet ac convallis et, semper et leo. Fusce ornare, risus ut porta tristique, purus lacus ultricies ante, ac semper metus eros quis sapien. Nunc vulputate neque ut efficitur condimentum. Quisque facilisis lacus at lorem condimentum suscipit. Aenean volutpat et dui non pharetra. Pellentesque pretium euismod sollicitudin. Phasellus ullamcorper nulla quis nibh tincidunt consectetur. Nulla gravida finibus mi, sed elementum ligula maximus sed. Ut eu dignissim ex. Nullam vestibulum accumsan ex, ut facilisis elit facilisis scelerisque. Integer pellentesque, sem a molestie porta, tortor felis consectetur lorem, ut interdum lacus mauris vel nisi. Maecenas justo nulla, pharetra at malesuada ac, sollicitudin quis tortor. Integer vehicula, mauris ac tristique vehicula, leo nibh cursus sem, sed rhoncus libero sapien ac tellus."
And this is the script for the parent process:
open System
open System.Diagnostics
let handleErr (args : DataReceivedEventArgs) : unit =
Console.ForegroundColor <- ConsoleColor.Red
try stderr.WriteLine args.Data
finally Console.ResetColor ()
let p = new Process ()
p.StartInfo.FileName <- "fsi"
p.StartInfo.Arguments <- "child.fsx"
p.StartInfo.UseShellExecute <- false
p.StartInfo.RedirectStandardError <- true
p.ErrorDataReceived.Add handleErr
p.Start ()
p.BeginErrorReadLine ()
p.WaitForExit ()
The expected output of the child process would be a line in red, followed by a paragraph in yellow, and finally a paragraph in green. When I run the child process on its own that is what gets output. But when I run it through the parent process this happens:
You can see that the error message "The quick brown fox jumped over the lazy dog." printed in the middle of the paragraph that should have printed after it, and the foreground color is incorrect. I have tried to find a solution for this and failed so far, as none of the following things will work:
- Use locks to allow only one function to print to the console at once - This won't help because the functions are isolated across different processes, not just different threads.
- Redirect stdout as well as stderr - This makes it impossible to preserve the color of the messages written to stdout.
- Combine stderr with stdout - I need a way to distinguish between stderr and stdout, so that the parent process can tell if stderr has been written to.
Is there a way in the parent process that I can detect whether the child process has written to stderr, while not redirecting the stderr stream and still letting the child process handle logging to the console?
.net f# system.diagnostics processstartinfo redirectstandardoutput
Did you try my suggestion? did it work for you?
– AMieres
Nov 24 '18 at 21:20
@AMieres Thanks for the answer, I don't think it will work though because the parent and child need to be separate processes in my situation. As you said there probably isn't a way to make what I want work apart from using exit codes or IPC, I'll look into those.
– tjohnson
Nov 25 '18 at 0:54
You have to try it to be sure. I think you will be surprised.
– AMieres
Nov 25 '18 at 4:47
I am curious if you tried it and if this worked for you: This people seemed to be having the same issue: repl.it/site/blog/stderr
– AMieres
Dec 2 '18 at 21:55
@AMieres TheMailBoxProcessor
seems like a really good idea for concurrency. Unfortunately it's not ideal for my situation because I need to be able to run the child processes independently and have them print out to the console, rather than always using aMailbox
agent. I was able to work around the issue for my particular situation, but I'll keep your answer in mind for future work.
– tjohnson
Dec 17 '18 at 14:21
|
show 1 more comment
I have two programs that I am running, one of which is run as a child process by the other. When the child process writes to stderr, I want to capture that in the parent process so I can tell if there was an error, and then log the error message to the console just like the child process tried to do.
The problem is that the child process writes several lines of text to stdout immediately after writing to stderr. When the parent process intercepts stderr messages and logs them itself, they get written in parallel with the stdout messages and the text appears in the wrong order.
I have created two F# scripts as a minimal reproduction of this problem. This is the script for the child process:
open System
let logError (x : string) : unit =
Console.ForegroundColor <- ConsoleColor.Red
try stderr.WriteLine x
finally Console.ResetColor ()
let logWarning (x : string) : unit =
Console.ForegroundColor <- ConsoleColor.Yellow
try stdout.WriteLine x
finally Console.ResetColor ()
let logInfo (x : string) : unit =
Console.ForegroundColor <- ConsoleColor.Green
try stdout.WriteLine x
finally Console.ResetColor ()
logError "The quick brown fox jumps over the lazy dog."
logWarning "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc eu est ut arcu finibus iaculis. Maecenas dapibus luctus convallis. Donec tristique accumsan ante sit amet maximus. Sed molestie eros sit amet pretium rhoncus. Sed odio lectus, vestibulum vitae consequat sit amet, eleifend ac augue. Vivamus eros quam, lobortis eget consequat in, pulvinar vel dolor. Sed efficitur fermentum purus eu imperdiet. Mauris posuere, metus nec fringilla accumsan, massa nisi egestas augue, et tristique ligula dolor sit amet nibh. Proin ultricies fermentum tellus, vitae porttitor mauris elementum id. Donec arcu dolor, posuere vel efficitur ultrices, sollicitudin sit amet mauris. Sed eu suscipit leo, in vehicula sem. Morbi congue nibh vitae orci lobortis, gravida volutpat augue imperdiet. Phasellus fringilla arcu ac tellus porttitor mattis. Donec in ante vitae sem varius pulvinar."
logInfo "Nam lorem justo, laoreet ac convallis et, semper et leo. Fusce ornare, risus ut porta tristique, purus lacus ultricies ante, ac semper metus eros quis sapien. Nunc vulputate neque ut efficitur condimentum. Quisque facilisis lacus at lorem condimentum suscipit. Aenean volutpat et dui non pharetra. Pellentesque pretium euismod sollicitudin. Phasellus ullamcorper nulla quis nibh tincidunt consectetur. Nulla gravida finibus mi, sed elementum ligula maximus sed. Ut eu dignissim ex. Nullam vestibulum accumsan ex, ut facilisis elit facilisis scelerisque. Integer pellentesque, sem a molestie porta, tortor felis consectetur lorem, ut interdum lacus mauris vel nisi. Maecenas justo nulla, pharetra at malesuada ac, sollicitudin quis tortor. Integer vehicula, mauris ac tristique vehicula, leo nibh cursus sem, sed rhoncus libero sapien ac tellus."
And this is the script for the parent process:
open System
open System.Diagnostics
let handleErr (args : DataReceivedEventArgs) : unit =
Console.ForegroundColor <- ConsoleColor.Red
try stderr.WriteLine args.Data
finally Console.ResetColor ()
let p = new Process ()
p.StartInfo.FileName <- "fsi"
p.StartInfo.Arguments <- "child.fsx"
p.StartInfo.UseShellExecute <- false
p.StartInfo.RedirectStandardError <- true
p.ErrorDataReceived.Add handleErr
p.Start ()
p.BeginErrorReadLine ()
p.WaitForExit ()
The expected output of the child process would be a line in red, followed by a paragraph in yellow, and finally a paragraph in green. When I run the child process on its own that is what gets output. But when I run it through the parent process this happens:
You can see that the error message "The quick brown fox jumped over the lazy dog." printed in the middle of the paragraph that should have printed after it, and the foreground color is incorrect. I have tried to find a solution for this and failed so far, as none of the following things will work:
- Use locks to allow only one function to print to the console at once - This won't help because the functions are isolated across different processes, not just different threads.
- Redirect stdout as well as stderr - This makes it impossible to preserve the color of the messages written to stdout.
- Combine stderr with stdout - I need a way to distinguish between stderr and stdout, so that the parent process can tell if stderr has been written to.
Is there a way in the parent process that I can detect whether the child process has written to stderr, while not redirecting the stderr stream and still letting the child process handle logging to the console?
.net f# system.diagnostics processstartinfo redirectstandardoutput
I have two programs that I am running, one of which is run as a child process by the other. When the child process writes to stderr, I want to capture that in the parent process so I can tell if there was an error, and then log the error message to the console just like the child process tried to do.
The problem is that the child process writes several lines of text to stdout immediately after writing to stderr. When the parent process intercepts stderr messages and logs them itself, they get written in parallel with the stdout messages and the text appears in the wrong order.
I have created two F# scripts as a minimal reproduction of this problem. This is the script for the child process:
open System
let logError (x : string) : unit =
Console.ForegroundColor <- ConsoleColor.Red
try stderr.WriteLine x
finally Console.ResetColor ()
let logWarning (x : string) : unit =
Console.ForegroundColor <- ConsoleColor.Yellow
try stdout.WriteLine x
finally Console.ResetColor ()
let logInfo (x : string) : unit =
Console.ForegroundColor <- ConsoleColor.Green
try stdout.WriteLine x
finally Console.ResetColor ()
logError "The quick brown fox jumps over the lazy dog."
logWarning "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc eu est ut arcu finibus iaculis. Maecenas dapibus luctus convallis. Donec tristique accumsan ante sit amet maximus. Sed molestie eros sit amet pretium rhoncus. Sed odio lectus, vestibulum vitae consequat sit amet, eleifend ac augue. Vivamus eros quam, lobortis eget consequat in, pulvinar vel dolor. Sed efficitur fermentum purus eu imperdiet. Mauris posuere, metus nec fringilla accumsan, massa nisi egestas augue, et tristique ligula dolor sit amet nibh. Proin ultricies fermentum tellus, vitae porttitor mauris elementum id. Donec arcu dolor, posuere vel efficitur ultrices, sollicitudin sit amet mauris. Sed eu suscipit leo, in vehicula sem. Morbi congue nibh vitae orci lobortis, gravida volutpat augue imperdiet. Phasellus fringilla arcu ac tellus porttitor mattis. Donec in ante vitae sem varius pulvinar."
logInfo "Nam lorem justo, laoreet ac convallis et, semper et leo. Fusce ornare, risus ut porta tristique, purus lacus ultricies ante, ac semper metus eros quis sapien. Nunc vulputate neque ut efficitur condimentum. Quisque facilisis lacus at lorem condimentum suscipit. Aenean volutpat et dui non pharetra. Pellentesque pretium euismod sollicitudin. Phasellus ullamcorper nulla quis nibh tincidunt consectetur. Nulla gravida finibus mi, sed elementum ligula maximus sed. Ut eu dignissim ex. Nullam vestibulum accumsan ex, ut facilisis elit facilisis scelerisque. Integer pellentesque, sem a molestie porta, tortor felis consectetur lorem, ut interdum lacus mauris vel nisi. Maecenas justo nulla, pharetra at malesuada ac, sollicitudin quis tortor. Integer vehicula, mauris ac tristique vehicula, leo nibh cursus sem, sed rhoncus libero sapien ac tellus."
And this is the script for the parent process:
open System
open System.Diagnostics
let handleErr (args : DataReceivedEventArgs) : unit =
Console.ForegroundColor <- ConsoleColor.Red
try stderr.WriteLine args.Data
finally Console.ResetColor ()
let p = new Process ()
p.StartInfo.FileName <- "fsi"
p.StartInfo.Arguments <- "child.fsx"
p.StartInfo.UseShellExecute <- false
p.StartInfo.RedirectStandardError <- true
p.ErrorDataReceived.Add handleErr
p.Start ()
p.BeginErrorReadLine ()
p.WaitForExit ()
The expected output of the child process would be a line in red, followed by a paragraph in yellow, and finally a paragraph in green. When I run the child process on its own that is what gets output. But when I run it through the parent process this happens:
You can see that the error message "The quick brown fox jumped over the lazy dog." printed in the middle of the paragraph that should have printed after it, and the foreground color is incorrect. I have tried to find a solution for this and failed so far, as none of the following things will work:
- Use locks to allow only one function to print to the console at once - This won't help because the functions are isolated across different processes, not just different threads.
- Redirect stdout as well as stderr - This makes it impossible to preserve the color of the messages written to stdout.
- Combine stderr with stdout - I need a way to distinguish between stderr and stdout, so that the parent process can tell if stderr has been written to.
Is there a way in the parent process that I can detect whether the child process has written to stderr, while not redirecting the stderr stream and still letting the child process handle logging to the console?
.net f# system.diagnostics processstartinfo redirectstandardoutput
.net f# system.diagnostics processstartinfo redirectstandardoutput
edited Nov 22 '18 at 4:45
tjohnson
asked Nov 21 '18 at 22:21
tjohnsontjohnson
691916
691916
Did you try my suggestion? did it work for you?
– AMieres
Nov 24 '18 at 21:20
@AMieres Thanks for the answer, I don't think it will work though because the parent and child need to be separate processes in my situation. As you said there probably isn't a way to make what I want work apart from using exit codes or IPC, I'll look into those.
– tjohnson
Nov 25 '18 at 0:54
You have to try it to be sure. I think you will be surprised.
– AMieres
Nov 25 '18 at 4:47
I am curious if you tried it and if this worked for you: This people seemed to be having the same issue: repl.it/site/blog/stderr
– AMieres
Dec 2 '18 at 21:55
@AMieres TheMailBoxProcessor
seems like a really good idea for concurrency. Unfortunately it's not ideal for my situation because I need to be able to run the child processes independently and have them print out to the console, rather than always using aMailbox
agent. I was able to work around the issue for my particular situation, but I'll keep your answer in mind for future work.
– tjohnson
Dec 17 '18 at 14:21
|
show 1 more comment
Did you try my suggestion? did it work for you?
– AMieres
Nov 24 '18 at 21:20
@AMieres Thanks for the answer, I don't think it will work though because the parent and child need to be separate processes in my situation. As you said there probably isn't a way to make what I want work apart from using exit codes or IPC, I'll look into those.
– tjohnson
Nov 25 '18 at 0:54
You have to try it to be sure. I think you will be surprised.
– AMieres
Nov 25 '18 at 4:47
I am curious if you tried it and if this worked for you: This people seemed to be having the same issue: repl.it/site/blog/stderr
– AMieres
Dec 2 '18 at 21:55
@AMieres TheMailBoxProcessor
seems like a really good idea for concurrency. Unfortunately it's not ideal for my situation because I need to be able to run the child processes independently and have them print out to the console, rather than always using aMailbox
agent. I was able to work around the issue for my particular situation, but I'll keep your answer in mind for future work.
– tjohnson
Dec 17 '18 at 14:21
Did you try my suggestion? did it work for you?
– AMieres
Nov 24 '18 at 21:20
Did you try my suggestion? did it work for you?
– AMieres
Nov 24 '18 at 21:20
@AMieres Thanks for the answer, I don't think it will work though because the parent and child need to be separate processes in my situation. As you said there probably isn't a way to make what I want work apart from using exit codes or IPC, I'll look into those.
– tjohnson
Nov 25 '18 at 0:54
@AMieres Thanks for the answer, I don't think it will work though because the parent and child need to be separate processes in my situation. As you said there probably isn't a way to make what I want work apart from using exit codes or IPC, I'll look into those.
– tjohnson
Nov 25 '18 at 0:54
You have to try it to be sure. I think you will be surprised.
– AMieres
Nov 25 '18 at 4:47
You have to try it to be sure. I think you will be surprised.
– AMieres
Nov 25 '18 at 4:47
I am curious if you tried it and if this worked for you: This people seemed to be having the same issue: repl.it/site/blog/stderr
– AMieres
Dec 2 '18 at 21:55
I am curious if you tried it and if this worked for you: This people seemed to be having the same issue: repl.it/site/blog/stderr
– AMieres
Dec 2 '18 at 21:55
@AMieres The
MailBoxProcessor
seems like a really good idea for concurrency. Unfortunately it's not ideal for my situation because I need to be able to run the child processes independently and have them print out to the console, rather than always using a Mailbox
agent. I was able to work around the issue for my particular situation, but I'll keep your answer in mind for future work.– tjohnson
Dec 17 '18 at 14:21
@AMieres The
MailBoxProcessor
seems like a really good idea for concurrency. Unfortunately it's not ideal for my situation because I need to be able to run the child processes independently and have them print out to the console, rather than always using a Mailbox
agent. I was able to work around the issue for my particular situation, but I'll keep your answer in mind for future work.– tjohnson
Dec 17 '18 at 14:21
|
show 1 more comment
1 Answer
1
active
oldest
votes
The typical way for a parent process to know if the child had an error is with the exit code when it is different than zero. Other than that you would need some other type of inter process communication.
I know you said that locks would not work but just in case, I will provide you this possible solution that works with the specific scenario you posted:
This one involves using MailBoxProcessor
to sequence the actions. First some helper functions:
module Mailbox =
/// A simple Mailbox processor to serially process Async tasks
/// use:
/// let logThisMsgA = Mailbox.iterA (printfn "%A") (fun msg -> async { printfn "Log: %s" msg } )
/// logThisMsgA.Post "message Async"
///
let iterA hndl f =
MailboxProcessor.Start(fun inbox ->
async {
while true do
try let! msg = inbox.Receive()
do! f msg
with e -> hndl e
}
)
/// A simple Mailbox processor to serially process tasks
/// use:
/// let logThisMsg = Mailbox.iter (printfn "%A") (printfn "Log: %s")
/// logThisMsg.Post "message"
///
let iter hndl f = iterA hndl (fun msg -> async { f msg } )
Here is the Mailbox agent and a function to invoke it:
let sequenceActions = Mailbox.iter (printfn "%A") (fun f -> f() )
let logSeq f txt = sequenceActions.Post <| fun () -> f txt
and your process invokes the functions this way:
logSeq logError "The quick brown fox jumps over the lazy dog."
logSeq logWarning "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc eu est ut arcu finibus iaculis. Maecenas dapibus luctus convallis. Donec tristique accumsan ante sit amet maximus. Sed molestie eros sit amet pretium rhoncus. Sed odio lectus, vestibulum vitae consequat sit amet, eleifend ac augue. Vivamus eros quam, lobortis eget consequat in, pulvinar vel dolor. Sed efficitur fermentum purus eu imperdiet. Mauris posuere, metus nec fringilla accumsan, massa nisi egestas augue, et tristique ligula dolor sit amet nibh. Proin ultricies fermentum tellus, vitae porttitor mauris elementum id. Donec arcu dolor, posuere vel efficitur ultrices, sollicitudin sit amet mauris. Sed eu suscipit leo, in vehicula sem. Morbi congue nibh vitae orci lobortis, gravida volutpat augue imperdiet. Phasellus fringilla arcu ac tellus porttitor mattis. Donec in ante vitae sem varius pulvinar."
logSeq logInfo "Nam lorem justo, laoreet ac convallis et, semper et leo. Fusce ornare, risus ut porta tristique, purus lacus ultricies ante, ac semper metus eros quis sapien. Nunc vulputate neque ut efficitur condimentum. Quisque facilisis lacus at lorem condimentum suscipit. Aenean volutpat et dui non pharetra. Pellentesque pretium euismod sollicitudin. Phasellus ullamcorper nulla quis nibh tincidunt consectetur. Nulla gravida finibus mi, sed elementum ligula maximus sed. Ut eu dignissim ex. Nullam vestibulum accumsan ex, ut facilisis elit facilisis scelerisque. Integer pellentesque, sem a molestie porta, tortor felis consectetur lorem, ut interdum lacus mauris vel nisi. Maecenas justo nulla, pharetra at malesuada ac, sollicitudin quis tortor. Integer vehicula, mauris ac tristique vehicula, leo nibh cursus sem, sed rhoncus libero sapien ac tellus."
I hope this helps.
add a comment |
Your Answer
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53421257%2fhow-to-redirect-error-but-not-output-and-keep-text-written-to-console-in-the-rig%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
The typical way for a parent process to know if the child had an error is with the exit code when it is different than zero. Other than that you would need some other type of inter process communication.
I know you said that locks would not work but just in case, I will provide you this possible solution that works with the specific scenario you posted:
This one involves using MailBoxProcessor
to sequence the actions. First some helper functions:
module Mailbox =
/// A simple Mailbox processor to serially process Async tasks
/// use:
/// let logThisMsgA = Mailbox.iterA (printfn "%A") (fun msg -> async { printfn "Log: %s" msg } )
/// logThisMsgA.Post "message Async"
///
let iterA hndl f =
MailboxProcessor.Start(fun inbox ->
async {
while true do
try let! msg = inbox.Receive()
do! f msg
with e -> hndl e
}
)
/// A simple Mailbox processor to serially process tasks
/// use:
/// let logThisMsg = Mailbox.iter (printfn "%A") (printfn "Log: %s")
/// logThisMsg.Post "message"
///
let iter hndl f = iterA hndl (fun msg -> async { f msg } )
Here is the Mailbox agent and a function to invoke it:
let sequenceActions = Mailbox.iter (printfn "%A") (fun f -> f() )
let logSeq f txt = sequenceActions.Post <| fun () -> f txt
and your process invokes the functions this way:
logSeq logError "The quick brown fox jumps over the lazy dog."
logSeq logWarning "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc eu est ut arcu finibus iaculis. Maecenas dapibus luctus convallis. Donec tristique accumsan ante sit amet maximus. Sed molestie eros sit amet pretium rhoncus. Sed odio lectus, vestibulum vitae consequat sit amet, eleifend ac augue. Vivamus eros quam, lobortis eget consequat in, pulvinar vel dolor. Sed efficitur fermentum purus eu imperdiet. Mauris posuere, metus nec fringilla accumsan, massa nisi egestas augue, et tristique ligula dolor sit amet nibh. Proin ultricies fermentum tellus, vitae porttitor mauris elementum id. Donec arcu dolor, posuere vel efficitur ultrices, sollicitudin sit amet mauris. Sed eu suscipit leo, in vehicula sem. Morbi congue nibh vitae orci lobortis, gravida volutpat augue imperdiet. Phasellus fringilla arcu ac tellus porttitor mattis. Donec in ante vitae sem varius pulvinar."
logSeq logInfo "Nam lorem justo, laoreet ac convallis et, semper et leo. Fusce ornare, risus ut porta tristique, purus lacus ultricies ante, ac semper metus eros quis sapien. Nunc vulputate neque ut efficitur condimentum. Quisque facilisis lacus at lorem condimentum suscipit. Aenean volutpat et dui non pharetra. Pellentesque pretium euismod sollicitudin. Phasellus ullamcorper nulla quis nibh tincidunt consectetur. Nulla gravida finibus mi, sed elementum ligula maximus sed. Ut eu dignissim ex. Nullam vestibulum accumsan ex, ut facilisis elit facilisis scelerisque. Integer pellentesque, sem a molestie porta, tortor felis consectetur lorem, ut interdum lacus mauris vel nisi. Maecenas justo nulla, pharetra at malesuada ac, sollicitudin quis tortor. Integer vehicula, mauris ac tristique vehicula, leo nibh cursus sem, sed rhoncus libero sapien ac tellus."
I hope this helps.
add a comment |
The typical way for a parent process to know if the child had an error is with the exit code when it is different than zero. Other than that you would need some other type of inter process communication.
I know you said that locks would not work but just in case, I will provide you this possible solution that works with the specific scenario you posted:
This one involves using MailBoxProcessor
to sequence the actions. First some helper functions:
module Mailbox =
/// A simple Mailbox processor to serially process Async tasks
/// use:
/// let logThisMsgA = Mailbox.iterA (printfn "%A") (fun msg -> async { printfn "Log: %s" msg } )
/// logThisMsgA.Post "message Async"
///
let iterA hndl f =
MailboxProcessor.Start(fun inbox ->
async {
while true do
try let! msg = inbox.Receive()
do! f msg
with e -> hndl e
}
)
/// A simple Mailbox processor to serially process tasks
/// use:
/// let logThisMsg = Mailbox.iter (printfn "%A") (printfn "Log: %s")
/// logThisMsg.Post "message"
///
let iter hndl f = iterA hndl (fun msg -> async { f msg } )
Here is the Mailbox agent and a function to invoke it:
let sequenceActions = Mailbox.iter (printfn "%A") (fun f -> f() )
let logSeq f txt = sequenceActions.Post <| fun () -> f txt
and your process invokes the functions this way:
logSeq logError "The quick brown fox jumps over the lazy dog."
logSeq logWarning "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc eu est ut arcu finibus iaculis. Maecenas dapibus luctus convallis. Donec tristique accumsan ante sit amet maximus. Sed molestie eros sit amet pretium rhoncus. Sed odio lectus, vestibulum vitae consequat sit amet, eleifend ac augue. Vivamus eros quam, lobortis eget consequat in, pulvinar vel dolor. Sed efficitur fermentum purus eu imperdiet. Mauris posuere, metus nec fringilla accumsan, massa nisi egestas augue, et tristique ligula dolor sit amet nibh. Proin ultricies fermentum tellus, vitae porttitor mauris elementum id. Donec arcu dolor, posuere vel efficitur ultrices, sollicitudin sit amet mauris. Sed eu suscipit leo, in vehicula sem. Morbi congue nibh vitae orci lobortis, gravida volutpat augue imperdiet. Phasellus fringilla arcu ac tellus porttitor mattis. Donec in ante vitae sem varius pulvinar."
logSeq logInfo "Nam lorem justo, laoreet ac convallis et, semper et leo. Fusce ornare, risus ut porta tristique, purus lacus ultricies ante, ac semper metus eros quis sapien. Nunc vulputate neque ut efficitur condimentum. Quisque facilisis lacus at lorem condimentum suscipit. Aenean volutpat et dui non pharetra. Pellentesque pretium euismod sollicitudin. Phasellus ullamcorper nulla quis nibh tincidunt consectetur. Nulla gravida finibus mi, sed elementum ligula maximus sed. Ut eu dignissim ex. Nullam vestibulum accumsan ex, ut facilisis elit facilisis scelerisque. Integer pellentesque, sem a molestie porta, tortor felis consectetur lorem, ut interdum lacus mauris vel nisi. Maecenas justo nulla, pharetra at malesuada ac, sollicitudin quis tortor. Integer vehicula, mauris ac tristique vehicula, leo nibh cursus sem, sed rhoncus libero sapien ac tellus."
I hope this helps.
add a comment |
The typical way for a parent process to know if the child had an error is with the exit code when it is different than zero. Other than that you would need some other type of inter process communication.
I know you said that locks would not work but just in case, I will provide you this possible solution that works with the specific scenario you posted:
This one involves using MailBoxProcessor
to sequence the actions. First some helper functions:
module Mailbox =
/// A simple Mailbox processor to serially process Async tasks
/// use:
/// let logThisMsgA = Mailbox.iterA (printfn "%A") (fun msg -> async { printfn "Log: %s" msg } )
/// logThisMsgA.Post "message Async"
///
let iterA hndl f =
MailboxProcessor.Start(fun inbox ->
async {
while true do
try let! msg = inbox.Receive()
do! f msg
with e -> hndl e
}
)
/// A simple Mailbox processor to serially process tasks
/// use:
/// let logThisMsg = Mailbox.iter (printfn "%A") (printfn "Log: %s")
/// logThisMsg.Post "message"
///
let iter hndl f = iterA hndl (fun msg -> async { f msg } )
Here is the Mailbox agent and a function to invoke it:
let sequenceActions = Mailbox.iter (printfn "%A") (fun f -> f() )
let logSeq f txt = sequenceActions.Post <| fun () -> f txt
and your process invokes the functions this way:
logSeq logError "The quick brown fox jumps over the lazy dog."
logSeq logWarning "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc eu est ut arcu finibus iaculis. Maecenas dapibus luctus convallis. Donec tristique accumsan ante sit amet maximus. Sed molestie eros sit amet pretium rhoncus. Sed odio lectus, vestibulum vitae consequat sit amet, eleifend ac augue. Vivamus eros quam, lobortis eget consequat in, pulvinar vel dolor. Sed efficitur fermentum purus eu imperdiet. Mauris posuere, metus nec fringilla accumsan, massa nisi egestas augue, et tristique ligula dolor sit amet nibh. Proin ultricies fermentum tellus, vitae porttitor mauris elementum id. Donec arcu dolor, posuere vel efficitur ultrices, sollicitudin sit amet mauris. Sed eu suscipit leo, in vehicula sem. Morbi congue nibh vitae orci lobortis, gravida volutpat augue imperdiet. Phasellus fringilla arcu ac tellus porttitor mattis. Donec in ante vitae sem varius pulvinar."
logSeq logInfo "Nam lorem justo, laoreet ac convallis et, semper et leo. Fusce ornare, risus ut porta tristique, purus lacus ultricies ante, ac semper metus eros quis sapien. Nunc vulputate neque ut efficitur condimentum. Quisque facilisis lacus at lorem condimentum suscipit. Aenean volutpat et dui non pharetra. Pellentesque pretium euismod sollicitudin. Phasellus ullamcorper nulla quis nibh tincidunt consectetur. Nulla gravida finibus mi, sed elementum ligula maximus sed. Ut eu dignissim ex. Nullam vestibulum accumsan ex, ut facilisis elit facilisis scelerisque. Integer pellentesque, sem a molestie porta, tortor felis consectetur lorem, ut interdum lacus mauris vel nisi. Maecenas justo nulla, pharetra at malesuada ac, sollicitudin quis tortor. Integer vehicula, mauris ac tristique vehicula, leo nibh cursus sem, sed rhoncus libero sapien ac tellus."
I hope this helps.
The typical way for a parent process to know if the child had an error is with the exit code when it is different than zero. Other than that you would need some other type of inter process communication.
I know you said that locks would not work but just in case, I will provide you this possible solution that works with the specific scenario you posted:
This one involves using MailBoxProcessor
to sequence the actions. First some helper functions:
module Mailbox =
/// A simple Mailbox processor to serially process Async tasks
/// use:
/// let logThisMsgA = Mailbox.iterA (printfn "%A") (fun msg -> async { printfn "Log: %s" msg } )
/// logThisMsgA.Post "message Async"
///
let iterA hndl f =
MailboxProcessor.Start(fun inbox ->
async {
while true do
try let! msg = inbox.Receive()
do! f msg
with e -> hndl e
}
)
/// A simple Mailbox processor to serially process tasks
/// use:
/// let logThisMsg = Mailbox.iter (printfn "%A") (printfn "Log: %s")
/// logThisMsg.Post "message"
///
let iter hndl f = iterA hndl (fun msg -> async { f msg } )
Here is the Mailbox agent and a function to invoke it:
let sequenceActions = Mailbox.iter (printfn "%A") (fun f -> f() )
let logSeq f txt = sequenceActions.Post <| fun () -> f txt
and your process invokes the functions this way:
logSeq logError "The quick brown fox jumps over the lazy dog."
logSeq logWarning "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc eu est ut arcu finibus iaculis. Maecenas dapibus luctus convallis. Donec tristique accumsan ante sit amet maximus. Sed molestie eros sit amet pretium rhoncus. Sed odio lectus, vestibulum vitae consequat sit amet, eleifend ac augue. Vivamus eros quam, lobortis eget consequat in, pulvinar vel dolor. Sed efficitur fermentum purus eu imperdiet. Mauris posuere, metus nec fringilla accumsan, massa nisi egestas augue, et tristique ligula dolor sit amet nibh. Proin ultricies fermentum tellus, vitae porttitor mauris elementum id. Donec arcu dolor, posuere vel efficitur ultrices, sollicitudin sit amet mauris. Sed eu suscipit leo, in vehicula sem. Morbi congue nibh vitae orci lobortis, gravida volutpat augue imperdiet. Phasellus fringilla arcu ac tellus porttitor mattis. Donec in ante vitae sem varius pulvinar."
logSeq logInfo "Nam lorem justo, laoreet ac convallis et, semper et leo. Fusce ornare, risus ut porta tristique, purus lacus ultricies ante, ac semper metus eros quis sapien. Nunc vulputate neque ut efficitur condimentum. Quisque facilisis lacus at lorem condimentum suscipit. Aenean volutpat et dui non pharetra. Pellentesque pretium euismod sollicitudin. Phasellus ullamcorper nulla quis nibh tincidunt consectetur. Nulla gravida finibus mi, sed elementum ligula maximus sed. Ut eu dignissim ex. Nullam vestibulum accumsan ex, ut facilisis elit facilisis scelerisque. Integer pellentesque, sem a molestie porta, tortor felis consectetur lorem, ut interdum lacus mauris vel nisi. Maecenas justo nulla, pharetra at malesuada ac, sollicitudin quis tortor. Integer vehicula, mauris ac tristique vehicula, leo nibh cursus sem, sed rhoncus libero sapien ac tellus."
I hope this helps.
edited Nov 22 '18 at 4:40
answered Nov 22 '18 at 4:20
AMieresAMieres
2,6451511
2,6451511
add a comment |
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53421257%2fhow-to-redirect-error-but-not-output-and-keep-text-written-to-console-in-the-rig%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Did you try my suggestion? did it work for you?
– AMieres
Nov 24 '18 at 21:20
@AMieres Thanks for the answer, I don't think it will work though because the parent and child need to be separate processes in my situation. As you said there probably isn't a way to make what I want work apart from using exit codes or IPC, I'll look into those.
– tjohnson
Nov 25 '18 at 0:54
You have to try it to be sure. I think you will be surprised.
– AMieres
Nov 25 '18 at 4:47
I am curious if you tried it and if this worked for you: This people seemed to be having the same issue: repl.it/site/blog/stderr
– AMieres
Dec 2 '18 at 21:55
@AMieres The
MailBoxProcessor
seems like a really good idea for concurrency. Unfortunately it's not ideal for my situation because I need to be able to run the child processes independently and have them print out to the console, rather than always using aMailbox
agent. I was able to work around the issue for my particular situation, but I'll keep your answer in mind for future work.– tjohnson
Dec 17 '18 at 14:21