Permalink
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Browse files
[processing] Fix GDAL algorithms hang when gdal command is not availa…
Loading branch information
@@ -129,6 +129,13 @@ After execution completes, the process' result code will be returned.
QProcess::ExitStatus exitStatus() const;
%Docstring
After a call to :py:func:`~QgsBlockingProcess.run`, returns the process' exit status.
%End
QProcess::ProcessError processError() const;
%Docstring
After a call to :py:func:`~QgsBlockingProcess.run`, returns the process' reported error.
Returns QProcess.UnknownError if no error occurred.
%End
};
@@ -150,6 +150,8 @@ def on_stderr(ba):
raise QgsProcessingException (GdalUtils .tr ('Process was unexpectedly terminated' ))
elif res == 0 :
feedback .pushInfo (GdalUtils .tr ('Process completed successfully' ))
elif proc .processError () == QProcess .FailedToStart :
raise QgsProcessingException (GdalUtils .tr ('Process {} failed to start. Either {} is missing, or you may have insufficient permissions to run the program.' ).format (command , command ))
else :
feedback .reportError (GdalUtils .tr ('Process returned error code {}' ).format (res ))
@@ -272,8 +272,9 @@ int QgsBlockingProcess::run( QgsFeedback *feedback )
int result = 0 ;
QProcess::ExitStatus exitStatus = QProcess::NormalExit;
QProcess::ProcessError error = QProcess::UnknownError;
std::function<void ()> runFunction = [ this , &result, &exitStatus, feedback]()
std::function<void ()> runFunction = [ this , &result, &exitStatus, &error, feedback]()
{
// this function will always be run in worker threads -- either the blocking call is being made in a worker thread,
// or the blocking call has been made from the main thread and we've fired up a new thread for this function
@@ -319,8 +320,16 @@ int QgsBlockingProcess::run( QgsFeedback *feedback )
mStderrHandler ( ba );
} );
p.start ( mProcess , mArguments , QProcess::Unbuffered | QProcess::ReadWrite );
loop.exec ();
if ( !p.waitForStarted () )
{
result = 1 ;
exitStatus = QProcess::NormalExit;
error = p.error ();
}
else
{
loop.exec ();
}
mStdoutHandler ( p.readAllStandardOutput () );
mStderrHandler ( p.readAllStandardError () );
@@ -339,11 +348,17 @@ int QgsBlockingProcess::run( QgsFeedback *feedback )
}
mExitStatus = exitStatus;
mProcessError = error;
return result;
}
QProcess::ExitStatus QgsBlockingProcess::exitStatus () const
{
return mExitStatus ;
};
QProcess::ProcessError QgsBlockingProcess::processError () const
{
return mProcessError ;
};
#endif // QT_CONFIG(process)
@@ -185,6 +185,13 @@ class CORE_EXPORT QgsBlockingProcess : public QObject
*/
QProcess::ExitStatus exitStatus () const ;
/* *
* After a call to run(), returns the process' reported error.
*
* Returns QProcess::UnknownError if no error occurred.
*/
QProcess::ProcessError processError () const ;
private:
QString mProcess ;
@@ -193,6 +200,7 @@ class CORE_EXPORT QgsBlockingProcess : public QObject
std::function< void ( const QByteArray & ) > mStderrHandler ;
QProcess::ExitStatus mExitStatus = QProcess::NormalExit;
QProcess::ProcessError mProcessError = QProcess::UnknownError;
};
#endif // QT_CONFIG(process)
@@ -113,6 +113,31 @@ def std_err(ba):
self .assertNotEqual (p .run (f ), 0 )
self .assertEqual (p .exitStatus (), QProcess .CrashExit )
def test_process_no_file (self ):
"""
Test a script which doesn't exist
"""
def std_out (ba ):
std_out .val += ba .data ().decode ('UTF-8' )
std_out .val = ''
def std_err (ba ):
std_err .val += ba .data ().decode ('UTF-8' )
std_err .val = ''
# this program definitely doesn't exist!
p = QgsBlockingProcess ('qgis_sucks' , ['--version' ])
p .setStdOutHandler (std_out )
p .setStdErrHandler (std_err )
f = QgsFeedback ()
self .assertEqual (p .run (f ), 1 )
self .assertEqual (p .exitStatus (), QProcess .NormalExit )
self .assertEqual (p .processError (), QProcess .FailedToStart )
def test_process_env (self ):
"""
Test that process inherits system environment correctly
Toggle all file notes