Farid Zaripov wrote:
 > -----Original Message-----
 > From: Martin Sebor [mailto:[EMAIL PROTECTED]
 > Sent: Friday, July 07, 2006 3:46 AM
 > To: [email protected]
 > Subject: Re: string methods thread safety
 >
 > Martin Sebor wrote:
[...]
 > This last part would be best implemented in the test driver
 > under some generic interface similar to rw_thread_create()
 > (e.g., rw_process_create()).

Martin, I implemented the functions rw_process_create() and rw_process_join():

Cool, this will be useful!

I would move these two functions to a different header/source file,
say rw_process.h and process.cpp. We can also move rw_system() to
the same files and get rid of system.h and system.cpp.


--------------------------------------
typedef long rw_pid_t;

// returns pid of the created process
// returns -1 if failed
// note: argv[0] should be equal to path
_TEST_EXPORT rw_pid_t
rw_process_create (const char* path, char* const argv []);

I'm not sure about the second argument. Is it the most convenient
interface? Wouldn't something closer to rw_system() be easier to
use? (If so, you might want to move rw_process_create to the .cpp
file and make it static and call it from the new vararg function).


// returns pid of the specified process
// returns -1 if failed
// result is a pointer to a buffer where the result code
// of the specified process will be stored, or NULL
_TEST_EXPORT rw_pid_t
rw_process_join (rw_pid_t pid, int* result);

Okay, this is close to waitpid() that I would suggest to rename
it to simply rw_waitpid() :)

[...]
+static rw_pid_t spawnv(int, const char* path, char* const argv [])
+{
+    if (rw_pid_t child_pid = fork ())
+        // the parent process
+        return child_pid;

Make sure to check child_pid for failure and report it, probably
via a call to rw_error(), before calling exec.

+
+    // the child process
+    execv (path, argv);
+
+    // the execvp returns only if an error occurs
+    rw_fatal (0, __FILE__, __LINE__, "execvp failed: : errno = %{#m} (%{m})");
+
+    exit (1);

FYI: rw_fatal() doesn't return so there's no need to call exit().

I'm not sure rw_fatal() is appropriate, though. The test might be
able to continue with other things after a failure. I think I would
go with rw_error() instead. You might also want to add a return
statement to avoid compiler warnings.

(Actually, having said that, since (I assume) this is a Windows
compatibility layer to make it transparent to callers whether
they are calling the Win32 API or not, the rw_error() calls in
response to errors should probably be made in the callers below).

+}
+
+static rw_pid_t cwait(int* status, rw_pid_t pid, int)
+{
+    const rw_pid_t res = waitpid (pid, status, 0);
+
+    if (res == pid && status)
+        *status = WEXITSTATUS (*status);
+
+    return res;
+}
+
+#endif
+
+extern "C" {
+
+_TEST_EXPORT rw_pid_t
+rw_process_create (const char* path, char* const argv[])
+{
+    return spawnv (P_NOWAIT, path, argv);

This is where I think all errors should be handled (you might
end up with more #ifdef _WIN32 conditionals if the error codes
are different between Windows and UNIX).

+}
+
+_TEST_EXPORT rw_pid_t
+rw_process_join (rw_pid_t pid, int* result)
+{
+    return cwait (result, pid, WAIT_CHILD);

Same here.

Martin

Reply via email to