* switch output and error stream to non blocking and snooze between each run.
* read error messages and present an alert with the option to stop processing * should fix #1870 and help with #5009 git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@38871 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
parent
97176323ed
commit
750111c966
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2004-2006, Jérôme Duval. All rights reserved.
|
* Copyright 2004-2010, Jérôme Duval. All rights reserved.
|
||||||
* Distributed under the terms of the MIT License.
|
* Distributed under the terms of the MIT License.
|
||||||
* Original code from ZipOMatic by jonas.sundstrom@kirilla.com
|
* Original code from ZipOMatic by jonas.sundstrom@kirilla.com
|
||||||
*/
|
*/
|
||||||
@ -21,8 +21,7 @@ ExpanderThread::ExpanderThread(BMessage * refs_message, BMessenger * messenger)
|
|||||||
fStdOut(-1),
|
fStdOut(-1),
|
||||||
fStdErr(-1),
|
fStdErr(-1),
|
||||||
fExpanderOutput(NULL),
|
fExpanderOutput(NULL),
|
||||||
fExpanderOutputString(),
|
fExpanderError(NULL)
|
||||||
fExpanderOutputBuffer(new char [4096])
|
|
||||||
{
|
{
|
||||||
SetDataStore(new BMessage(* refs_message)); // leak?
|
SetDataStore(new BMessage(* refs_message)); // leak?
|
||||||
// prevents bug with B_SIMPLE_DATA
|
// prevents bug with B_SIMPLE_DATA
|
||||||
@ -33,16 +32,15 @@ ExpanderThread::ExpanderThread(BMessage * refs_message, BMessenger * messenger)
|
|||||||
ExpanderThread::~ExpanderThread()
|
ExpanderThread::~ExpanderThread()
|
||||||
{
|
{
|
||||||
delete fWindowMessenger;
|
delete fWindowMessenger;
|
||||||
delete [] fExpanderOutputBuffer;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
ExpanderThread::ThreadStartup()
|
ExpanderThread::ThreadStartup()
|
||||||
{
|
{
|
||||||
status_t status = B_OK;
|
status_t status = B_OK;
|
||||||
entry_ref srcRef, destRef;
|
entry_ref srcRef, destRef;
|
||||||
BString cmd;
|
BString cmd;
|
||||||
|
|
||||||
if ((status = GetDataStore()->FindRef("srcRef", &srcRef)) != B_OK)
|
if ((status = GetDataStore()->FindRef("srcRef", &srcRef)) != B_OK)
|
||||||
return status;
|
return status;
|
||||||
@ -63,9 +61,9 @@ ExpanderThread::ThreadStartup()
|
|||||||
int32 argc = 3;
|
int32 argc = 3;
|
||||||
const char ** argv = new const char * [argc + 1];
|
const char ** argv = new const char * [argc + 1];
|
||||||
|
|
||||||
argv[0] = strdup("/bin/sh");
|
argv[0] = strdup("/bin/sh");
|
||||||
argv[1] = strdup("-c");
|
argv[1] = strdup("-c");
|
||||||
argv[2] = strdup(cmd.String());
|
argv[2] = strdup(cmd.String());
|
||||||
argv[argc] = NULL;
|
argv[argc] = NULL;
|
||||||
|
|
||||||
fThreadId = PipeCommand(argc, argv, fStdIn, fStdOut, fStdErr);
|
fThreadId = PipeCommand(argc, argv, fStdIn, fStdOut, fStdErr);
|
||||||
@ -79,9 +77,17 @@ ExpanderThread::ThreadStartup()
|
|||||||
set_thread_priority(fThreadId, B_LOW_PRIORITY);
|
set_thread_priority(fThreadId, B_LOW_PRIORITY);
|
||||||
|
|
||||||
resume_thread(fThreadId);
|
resume_thread(fThreadId);
|
||||||
|
|
||||||
|
int flags = fcntl(fStdOut, F_GETFL, 0);
|
||||||
|
flags |= O_NONBLOCK;
|
||||||
|
fcntl(fStdOut, F_SETFL, flags);
|
||||||
|
flags = fcntl(fStdErr, F_GETFL, 0);
|
||||||
|
flags |= O_NONBLOCK;
|
||||||
|
fcntl(fStdErr, F_SETFL, flags);
|
||||||
|
|
||||||
fExpanderOutput = fdopen(fStdOut, "r");
|
fExpanderOutput = fdopen(fStdOut, "r");
|
||||||
|
fExpanderError = fdopen(fStdErr, "r");
|
||||||
|
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -89,23 +95,33 @@ ExpanderThread::ThreadStartup()
|
|||||||
status_t
|
status_t
|
||||||
ExpanderThread::ExecuteUnit(void)
|
ExpanderThread::ExecuteUnit(void)
|
||||||
{
|
{
|
||||||
// read output from command
|
// read output and error from command
|
||||||
// send it to window
|
// send it to window
|
||||||
|
|
||||||
char *output_string = fgets(fExpanderOutputBuffer , 4096 - 1, fExpanderOutput);
|
|
||||||
|
|
||||||
if (output_string == NULL)
|
|
||||||
return EOF;
|
|
||||||
|
|
||||||
BMessage message('outp');
|
BMessage message('outp');
|
||||||
message.AddString("output", output_string);
|
bool outputAdded = false;
|
||||||
for (int32 i = 0; i < 5; i++) {
|
for (int32 i = 0; i < 50; i++) {
|
||||||
output_string = fgets(fExpanderOutputBuffer , 4096 - 1, fExpanderOutput);
|
char *output_string = fgets(fExpanderOutputBuffer , LINE_MAX, fExpanderOutput);
|
||||||
if (!output_string)
|
if (!output_string)
|
||||||
break;
|
break;
|
||||||
message.AddString("output", output_string);
|
message.AddString("output", output_string);
|
||||||
|
outputAdded = true;
|
||||||
}
|
}
|
||||||
fWindowMessenger->SendMessage(&message);
|
if (outputAdded)
|
||||||
|
fWindowMessenger->SendMessage(&message);
|
||||||
|
if (feof(fExpanderOutput))
|
||||||
|
return EOF;
|
||||||
|
|
||||||
|
char *error_string = fgets(fExpanderOutputBuffer , LINE_MAX, fExpanderError);
|
||||||
|
if (error_string != NULL
|
||||||
|
&& strcmp(error_string, "\n")) {
|
||||||
|
BMessage message('errp');
|
||||||
|
message.AddString("error", error_string);
|
||||||
|
fWindowMessenger->SendMessage(&message);
|
||||||
|
}
|
||||||
|
|
||||||
|
// streams are non blocking, sleep every 100ms
|
||||||
|
snooze(100000);
|
||||||
|
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
@ -173,7 +189,7 @@ ExpanderThread::PipeCommand(int argc, const char **argv, int &in, int &out, int
|
|||||||
int old_err = dup(2);
|
int old_err = dup(2);
|
||||||
|
|
||||||
int filedes[2];
|
int filedes[2];
|
||||||
|
|
||||||
/* Create new pipe FDs as stdin, stdout, stderr */
|
/* Create new pipe FDs as stdin, stdout, stderr */
|
||||||
pipe(filedes); dup2(filedes[0], 0); close(filedes[0]);
|
pipe(filedes); dup2(filedes[0], 0); close(filedes[0]);
|
||||||
in = filedes[1]; // Write to in, appears on cmd's stdin
|
in = filedes[1]; // Write to in, appears on cmd's stdin
|
||||||
|
@ -1,30 +1,8 @@
|
|||||||
/*****************************************************************************/
|
/*
|
||||||
// Expander
|
* Copyright 2004-2010, Jérôme Duval. All rights reserved.
|
||||||
// Written by Jérôme Duval
|
* Distributed under the terms of the MIT License.
|
||||||
//
|
* Original code from ZipOMatic by jonas.sundstrom@kirilla.com
|
||||||
// ExpanderThread.h
|
*/
|
||||||
//
|
|
||||||
// Copyright (c) 2004 OpenBeOS Project
|
|
||||||
//
|
|
||||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
|
||||||
// copy of this software and associated documentation files (the "Software"),
|
|
||||||
// to deal in the Software without restriction, including without limitation
|
|
||||||
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
|
||||||
// and/or sell copies of the Software, and to permit persons to whom the
|
|
||||||
// Software is furnished to do so, subject to the following conditions:
|
|
||||||
//
|
|
||||||
// The above copyright notice and this permission notice shall be included
|
|
||||||
// in all copies or substantial portions of the Software.
|
|
||||||
//
|
|
||||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
|
||||||
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
|
||||||
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
||||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
|
||||||
// DEALINGS IN THE SOFTWARE.
|
|
||||||
/*****************************************************************************/
|
|
||||||
|
|
||||||
#ifndef __EXPANDERTHREAD_H__
|
#ifndef __EXPANDERTHREAD_H__
|
||||||
#define __EXPANDERTHREAD_H__
|
#define __EXPANDERTHREAD_H__
|
||||||
|
|
||||||
@ -74,8 +52,8 @@ class ExpanderThread : public GenericThread
|
|||||||
int fStdOut;
|
int fStdOut;
|
||||||
int fStdErr;
|
int fStdErr;
|
||||||
FILE * fExpanderOutput;
|
FILE * fExpanderOutput;
|
||||||
BString fExpanderOutputString;
|
FILE * fExpanderError;
|
||||||
char * fExpanderOutputBuffer;
|
char fExpanderOutputBuffer[LINE_MAX];
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // __EXPANDERTHREAD_H__
|
#endif // __EXPANDERTHREAD_H__
|
||||||
|
@ -337,7 +337,24 @@ ExpanderWindow::MessageReceived(BMessage* msg)
|
|||||||
fListingText->ScrollToSelection();
|
fListingText->ScrollToSelection();
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case 'errp':
|
||||||
|
{
|
||||||
|
BString string;
|
||||||
|
if (msg->FindString("error", &string) == B_OK
|
||||||
|
&& fExpandingStarted) {
|
||||||
|
fExpandingThread->SuspendExternalExpander();
|
||||||
|
BAlert* alert = new BAlert("stopAlert", string,
|
||||||
|
B_TRANSLATE("Stop"), B_TRANSLATE("Continue"), NULL,
|
||||||
|
B_WIDTH_AS_USUAL, B_EVEN_SPACING, B_WARNING_ALERT);
|
||||||
|
if (alert->Go() == 0) {
|
||||||
|
fExpandingThread->ResumeExternalExpander();
|
||||||
|
StopExpanding();
|
||||||
|
} else
|
||||||
|
fExpandingThread->ResumeExternalExpander();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
case 'exit':
|
case 'exit':
|
||||||
// thread has finished (finished, quit, killed, we don't know)
|
// thread has finished (finished, quit, killed, we don't know)
|
||||||
// reset window state
|
// reset window state
|
||||||
|
Loading…
Reference in New Issue
Block a user