site_archiver@lists.apple.com Delivered-To: darwin-dev@lists.apple.com #include <spawn.h> #include <sys/wait.h> #include <stdio.h> #include <errno.h> extern char **environ; -- Terry _______________________________________________ Do not post admin requests to the list. They will be ignored. Darwin-dev mailing list (Darwin-dev@lists.apple.com) Help/Unsubscribe/Update your Subscription: http://lists.apple.com/mailman/options/darwin-dev/site_archiver%40lists.appl... On Sep 25, 2009, at 11:07 PM, Steve Checkoway <s@pahtak.org> wrote: On Sep 25, 2009, at 4:24 PM, Terry Lambert wrote: We don't support all of POSIX RT. The option set that that's in is actially AIO, which is a subset of RT, and we don't se _POSIX_ASYNCHRONOUS_IO in <unistd.h> because we don't support one of the option flags to aio_fsync() in a POSIX compliant way. So this seems like a case where relying on the version test macros in unistd.h as a method of determining the usability of a function rather than a link test is incorrect. Except you can't run partial test sets when running the conformance tests, so it's impossible to know without the feature test macros whether or not the behaviour of the interface, to the extent it is implemented, is in fact POSIX compliant. And, indeed, I know for a fact that it is not; however, I also happen to know that, to the extent he would be using it as a replacement for read in the use model he's reported to us, it'd work well enough for him. Just glancing through the list for the first time, I see _POSIX_SPAWN is defined as -1 but I thought posix_spawn() was supported. That feature test macro is defined that way for two reasons, even though Apple makes extensive use of posix_spawn() practically everywhere {v}fork()/execve() was used in prior OS releases: 1) the gcc compiler is broken in that it can't handle a non-variable containing prototype using the "restrict" keyword interior to an array declaration, so it's not possible to implement the prototype in a completely compliant way. 2) we wanted some "bake time" before everyone and their dog jumped in and started using it, and not advertising it was the best way to let us change its behaviour in future releases, without breaking too many people. The following works for me, at least. It seems like the only sure way to check if something will work is to write test code trying it since one cannot rely on the version test macros nor on link tests. In retrospect, this is obvious. int main( int argc, char *argv[] ) { if( argc < 2 ) return 1; pid_t pid; int status; int ret = posix_spawnp( &pid, argv[1], NULL, NULL, argv+1, environ ); if( ret != 0 ) { errno = ret; // lazy perror( "posix_spawn" ); return 1; } ret = waitpid( pid, &status, 0 ); if( ret == -1 ) { perror( "waitpid" ); return 2; } if( WIFEXITED(status) ) printf( "Exited normally with status %d\n", WEXITSTATUS(status) ); else if( WIFSIGNALED(status) ) printf( "Terminated due to signal %d\n", WTERMSIG (status) ); else puts( "Something else" ); return 0; } You did the "errno = ret;"... a lazier programmer might not have done that, and if they didn't, and their program was multiththreaded, they'd maybe see one thing that we already know we have to fix about the implementation to make it more strictly compliant (i.e. it sometimes smashes errno, but not for all errors). Like I said, it needs some "bake time". Likewise, it'd be possible to use per-thread current working directories to implement the HPC interfaces openat(), etc.. You'd actually not want to use them mostly, since per-thread current working directories are vastly superior to those interfaces for most uses to which they are put (e.g. virtual hosting and cgi sandboxing in web servers, etc.), they are just hard to implement in a lot of OSs, so people hacked around it by using up a bunch if fds as directory handles instead (hint: consider any OS without a 1:1 threading model). But if we implemented the HPC library functions before they were actually standardized, people started depending on some quirk of the draft standard, and that was later eliminated by the standards committee, people who implemented to our version would be in trouble over portability, and we'd be in trouble over standards compliance. So rather than implement a bunch of _np versions of largely inferior standards track interfaces, we don't implement them, and we point people who ask for them at per thread current working directories instead. Of course, standards committees may not catch their mistakes; lchown (), for example, was standardized as returning an errno of EOPNOTSUPP for an FS implementation not supporting changing ownership of symlinks; that's "operation not supported on socket", as opposed to the correct errno value, which would have been ENOTSUP, "not supported". And that's totally side-stepping the questionable utility of an lchown() in a standard which omits lchmod(), or the questionable utility of a function it would be a completly standards compliantl implementation of to just always set errno EOPNOTSUPP. But depending on them making such a mistake all the time would be a mistake. So there are, and probably always will be, interfaces which are "use at your own risk", which you will be able to find without the benefit of an OS contract about their adherence to standards (and an implied contract to not change unless the standard changes). If you want your code to be portable, you won't use them even if you are clever and find them without the feature test macros. Or, as in this case, you'll make a conscious trade-off between a potential loss of portability vs. greatly increased performance, and hopefully bracket your code with derived #ifdef's rather than direct #ifdef's. This email sent to site_archiver@lists.apple.com
participants (1)
-
Terry Lambert