the_Foundation [main]

Windows: Fixed process output reading, waiting for finish

=> 6ac8385d39bf7396589a3926d0d22f0958fd28a3

diff --git a/src/platform/win32/process.c b/src/platform/win32/process.c
index df1b5a9..36c8978 100644
--- a/src/platform/win32/process.c
+++ b/src/platform/win32/process.c
@@ -44,6 +44,7 @@ struct Impl_Process {
     iPipe pin;
     iPipe pout;
     iPipe perr;
+    iBlock *bufOut;
     PROCESS_INFORMATION procInfo;
     STARTUPINFOW startInfo;
     int exitStatus;
@@ -60,6 +61,7 @@ void init_Process(iProcess *d) {
     init_Pipe(&d->pin);
     init_Pipe(&d->pout);
     init_Pipe(&d->perr);
+    d->bufOut = new_Block(0);
     iZap(d->procInfo);
     d->startInfo = (STARTUPINFOW){
         .cb         = sizeof(d->startInfo),
@@ -93,6 +95,7 @@ void deinit_Process(iProcess *d) {
     deinit_Pipe(&d->pin);
     deinit_Pipe(&d->pout);
     deinit_Pipe(&d->perr);
+    delete_Block(d->bufOut);
 }
 
 void setArguments_Process(iProcess *d, const iStringList *args) {
@@ -132,24 +135,24 @@ iBool start_Process(iProcess *d) {
             delete_String(arg);
         }
     }
-    printf("cmdline: %s\n", cstr_String(cmdLine));
     /* The environment. */
     if (!isEmpty_StringList(d->envMods)) {
-        //iBlock *env = collect_Block(new_Block(0));
-        /* TODO: Compose the new environment strings */
-#if 0
-        for (const char *envList = GetEnvironmentStringsA(); *envList; ) {
-            size_t len = strlen(envList);
-            pushBack_Array(env, e);
+        iBlock *envUtf16 = collect_Block(new_Block(0));
+        for (const wchar_t *e = GetEnvironmentStringsW(); *e; ) {
+            size_t len = wcslen(e);
+            appendData_Block(envUtf16, e, (len + 1) * 2);
+            e += len + 1;
         }
         iConstForEach(StringList, e, d->envMods) {
-            pushBack_Array(env, &(const char *){ cstr_String(e.value) });
+            iBlock *wide = toUtf16_String(e.value);
+            append_Block(envUtf16, wide);
+            delete_Block(wide);
+            appendData_Block(envUtf16, &(wchar_t){ 0 }, 2);
         }
-        pushBack_Array(env, &(const char *){ NULL });
-        envs = (LPVOID) data_Array(env);
-#endif
+        appendData_Block(envUtf16, (wchar_t[]){ 0, 0 }, 4);
+        envs = (LPVOID) data_Block(envUtf16);
     }
-    DWORD creationFlags = 0;
+    DWORD creationFlags = CREATE_UNICODE_ENVIRONMENT;
     BOOL ok = CreateProcessW(
         NULL,
         (LPWSTR) toWide_CStr_(cstr_String(cmdLine)),
@@ -201,10 +204,14 @@ int exitStatus_Process(const iProcess *d) {
 
 void waitForFinished_Process(iProcess *d) {
     if (d->pid) {
+        iBlock *out = readOutputUntilClosed_Process(d);
+        append_Block(d->bufOut, out);
+        delete_Block(out);
         DWORD exitCode = 0;
-        WaitForSingleObject(d->procInfo.hProcess, INFINITE);
-        GetExitCodeProcess(d->procInfo.hProcess, &exitCode);
-        d->exitStatus = exitCode;
+        BOOL ok = GetExitCodeProcess(d->procInfo.hProcess, &exitCode);
+        if (ok) {
+            d->exitStatus = exitCode;
+        }
         d->pid = 0;
     }
 }
@@ -233,7 +240,9 @@ static iBlock *readFromPipe_(HANDLE pipe, iBlock *readChars) {
 }
 
 iBlock *readOutput_Process(iProcess *d) {
-    return readFromPipe_(output_Pipe(&d->pout), new_Block(0));
+    iBlock *buf = copy_Block(d->bufOut);
+    clear_Block(d->bufOut);
+    return readFromPipe_(output_Pipe(&d->pout), buf);
 }
 
 iBlock *readError_Process(iProcess *d) {
@@ -246,14 +255,13 @@ void kill_Process(iProcess *d) {
     }
 }
 
-iBlock *readOutputUntilClosed_Process(iProcess *d) {    
-    iBlock *output = new_Block(0);
+iBlock *readOutputUntilClosed_Process(iProcess *d) {
+    iBlock *output = copy_Block(d->bufOut);
+    clear_Block(d->bufOut);
     if (!d->pid) {
         return output;
     }
     HANDLE fd = output_Pipe(&d->pout);
-    //DWORD mode = PIPE_WAIT;
-    //SetNamedPipeHandleState(fd, &mode, NULL, NULL); /* blocking mode */
     CloseHandle(input_Pipe(&d->pin)); /* no more input */
     for (;;) {
         char buf[0x20000];
diff --git a/tests/t_process.c b/tests/t_process.c
index 44a9c67..e4ce122 100644
--- a/tests/t_process.c
+++ b/tests/t_process.c
@@ -30,6 +30,9 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #include 
 #include 
 
+#define TEST_MULTITHREAD 0
+
+#if TEST_MULTITHREAD
 iMutex mtx_; /* avoid pipe issues */
 
 static iThreadResult run_(iThread *d) {
@@ -64,10 +67,39 @@ static iThreadResult run_(iThread *d) {
     iRelease(args);
     return 0;
 }
+#endif
 
 int main(int argc, char *argv[]) {
     iUnused(argc, argv);    
     init_Foundation();
+    /* Test GUI launch. */ {
+        iProcess *proc = new_Process();
+        setArguments_Process(proc, iClob(newStringsCStr_StringList("c:\\windows\\notepad.exe", NULL)));
+        //start_Process(proc);
+        waitForFinished_Process(proc);
+        iRelease(proc);
+    }
+    /* Test arguments and environment. */ {
+        iProcess *proc = new_Process();
+        setArguments_Process(proc,
+                             iClob(newStringsCStr_StringList(
+                                 "c:\\msys64\\usr\\bin\\printenv.exe", NULL)));
+        setEnvironment_Process(proc,
+                               collect_StringList(newStringsCStr_StringList(
+                                   "TESTVALUE=Keränen", "OTHER=something with space", NULL)));
+        if (start_Process(proc))
+        {
+            waitForFinished_Process(proc);
+            iBlock *out = collect_Block(readOutput_Process(proc));
+            iString *outs = collect_String(newBlock_String(out));
+            printf("Child environment:\n%s\n", cstrLocal_String(outs));
+        }
+        else {
+            printf("Failed to start\n");
+        }
+        iRelease(proc);
+    }
+#if TEST_MULTITHREAD
     init_Mutex(&mtx_);
     iThread *thds[8];
     iForIndices(i, thds) {
@@ -77,7 +109,8 @@ int main(int argc, char *argv[]) {
     iForIndices(i, thds) {
         join_Thread(thds[i]);
         iRelease(thds[i]);
-    }    
+    }
+#endif
     deinit_Foundation();
     return 0;
 }
Proxy Information
Original URL
gemini://git.skyjake.fi/the_Foundation/main/cdiff/6ac8385d39bf7396589a3926d0d22f0958fd28a3
Status Code
Success (20)
Meta
text/gemini; charset=utf-8
Capsule Response Time
52.149089 milliseconds
Gemini-to-HTML Time
0.495187 milliseconds

This content has been proxied by September (ba2dc).