diff --git a/satella/processes.py b/satella/processes.py
index af56d19066b9656220807de8be0a74421c463fc0..c0dfbd9f477b4caeff1db2bdacb96c2bd5b89abd 100644
--- a/satella/processes.py
+++ b/satella/processes.py
@@ -19,15 +19,20 @@ def read_nowait(process: subprocess.Popen, output_list: tp.List[str]):
 
 def call_and_return_stdout(args: tp.Union[str, tp.List[str]],
                            timeout: tp.Optional[int] = None,
+                           encoding: tp.Optional[str] = None,
                            expected_return_code: int = 0, **kwargs) -> tp.Union[bytes, str]:
     """
     Call a process and return it's stdout.
 
     Everything in kwargs will be passed to subprocess.Popen
 
+    A bytes object will be returned if encoding is not defined, else stdout will be decoded
+    according to specified encoding
+
     :param args: arguments to run the program with. If passed a string, it will be split on space.
     :param timeout: amount of seconds to wait for the process result. If process does not complete
         within this time, it will be sent a SIGKILL
+    :param encoding: encoding with which to decode stdout. If none is passed, it will be returned as a bytes object
     :param expected_return_code: an expected return code of this process. 0 is the default. If process
         returns anything else, ProcessFailed will be raise
     :raises ProcessFailed: process' result code was different from the requested
@@ -47,13 +52,15 @@ def call_and_return_stdout(args: tp.Union[str, tp.List[str]],
     except subprocess.TimeoutExpired:
         proc.kill()
         proc.wait()
+    reader_thread.join()
 
     if proc.returncode != expected_return_code:
         raise ProcessFailed(proc.returncode)
     else:
-        if kwargs.get('encoding', None) is None:
+        if encoding is None:
             return b''.join(stdout_list)
         else:
-            return ''.join(stdout_list)
+
+            return ''.join((row.decode(encoding) for row in stdout_list))