diff options
Diffstat (limited to 'src/util/os_priority.c')
-rw-r--r-- | src/util/os_priority.c | 615 |
1 files changed, 1 insertions, 614 deletions
diff --git a/src/util/os_priority.c b/src/util/os_priority.c index ebe469b3b..e25623af5 100644 --- a/src/util/os_priority.c +++ b/src/util/os_priority.c | |||
@@ -350,7 +350,6 @@ start_process(int pipe_control, | |||
350 | const char *filename, | 350 | const char *filename, |
351 | char *const argv[]) | 351 | char *const argv[]) |
352 | { | 352 | { |
353 | #ifndef MINGW | ||
354 | pid_t ret; | 353 | pid_t ret; |
355 | char fds[16]; | 354 | char fds[16]; |
356 | struct GNUNET_OS_Process *gnunet_proc; | 355 | struct GNUNET_OS_Process *gnunet_proc; |
@@ -464,7 +463,7 @@ start_process(int pipe_control, | |||
464 | GNUNET_array_append(lscp, ls, -1); | 463 | GNUNET_array_append(lscp, ls, -1); |
465 | } | 464 | } |
466 | #if DARWIN | 465 | #if DARWIN |
467 | /* see https://gnunet.org/vfork */ | 466 | /* see https://web.archive.org/web/20150924082249/gnunet.org/vfork */ |
468 | ret = vfork(); | 467 | ret = vfork(); |
469 | #else | 468 | #else |
470 | ret = fork(); | 469 | ret = fork(); |
@@ -589,547 +588,6 @@ start_process(int pipe_control, | |||
589 | execvp(filename, argv); | 588 | execvp(filename, argv); |
590 | LOG_STRERROR_FILE(GNUNET_ERROR_TYPE_ERROR, "execvp", filename); | 589 | LOG_STRERROR_FILE(GNUNET_ERROR_TYPE_ERROR, "execvp", filename); |
591 | _exit(1); | 590 | _exit(1); |
592 | #else | ||
593 | struct GNUNET_DISK_FileHandle *childpipe_read; | ||
594 | struct GNUNET_DISK_FileHandle *childpipe_write; | ||
595 | HANDLE childpipe_read_handle; | ||
596 | char **arg; | ||
597 | char **non_const_argv; | ||
598 | unsigned int cmdlen; | ||
599 | char *cmd; | ||
600 | char *idx; | ||
601 | STARTUPINFOW start; | ||
602 | PROCESS_INFORMATION proc; | ||
603 | int argcount = 0; | ||
604 | struct GNUNET_OS_Process *gnunet_proc; | ||
605 | char path[MAX_PATH + 1]; | ||
606 | char *our_env[7] = { NULL, NULL, NULL, NULL, NULL, NULL, NULL }; | ||
607 | char *env_block = NULL; | ||
608 | char *pathbuf; | ||
609 | DWORD pathbuf_len; | ||
610 | DWORD alloc_len; | ||
611 | char *self_prefix; | ||
612 | char *bindir; | ||
613 | char *libdir; | ||
614 | char *ptr; | ||
615 | char *non_const_filename; | ||
616 | char win_path[MAX_PATH + 1]; | ||
617 | struct GNUNET_DISK_PipeHandle *lsocks_pipe; | ||
618 | const struct GNUNET_DISK_FileHandle *lsocks_write_fd; | ||
619 | HANDLE lsocks_read; | ||
620 | HANDLE lsocks_write; | ||
621 | wchar_t *wpath; | ||
622 | wchar_t *wcmd; | ||
623 | size_t wpath_len; | ||
624 | size_t wcmd_len; | ||
625 | int env_off; | ||
626 | int fail; | ||
627 | long lRet; | ||
628 | HANDLE stdin_handle; | ||
629 | HANDLE stdout_handle; | ||
630 | HANDLE stdih, stdoh, stdeh; | ||
631 | DWORD stdif, stdof, stdef; | ||
632 | BOOL bresult; | ||
633 | DWORD error_code; | ||
634 | DWORD create_no_window; | ||
635 | |||
636 | if (GNUNET_SYSERR == | ||
637 | GNUNET_OS_check_helper_binary(filename, GNUNET_NO, NULL)) | ||
638 | return NULL; /* not executable */ | ||
639 | |||
640 | /* Search in prefix dir (hopefully - the directory from which | ||
641 | * the current module was loaded), bindir and libdir, then in PATH | ||
642 | */ | ||
643 | self_prefix = GNUNET_OS_installation_get_path(GNUNET_OS_IPK_SELF_PREFIX); | ||
644 | bindir = GNUNET_OS_installation_get_path(GNUNET_OS_IPK_BINDIR); | ||
645 | libdir = GNUNET_OS_installation_get_path(GNUNET_OS_IPK_LIBDIR); | ||
646 | |||
647 | pathbuf_len = GetEnvironmentVariableA("PATH", (char *)&pathbuf, 0); | ||
648 | |||
649 | alloc_len = pathbuf_len + 1 + strlen(self_prefix) + 1 + strlen(bindir) + 1 + | ||
650 | strlen(libdir); | ||
651 | |||
652 | pathbuf = GNUNET_malloc(alloc_len * sizeof(char)); | ||
653 | |||
654 | ptr = pathbuf; | ||
655 | ptr += sprintf(pathbuf, "%s;%s;%s;", self_prefix, bindir, libdir); | ||
656 | GNUNET_free(self_prefix); | ||
657 | GNUNET_free(bindir); | ||
658 | GNUNET_free(libdir); | ||
659 | |||
660 | alloc_len = GetEnvironmentVariableA("PATH", ptr, pathbuf_len); | ||
661 | if (alloc_len != pathbuf_len - 1) | ||
662 | { | ||
663 | GNUNET_free(pathbuf); | ||
664 | errno = ENOSYS; /* PATH changed on the fly. What kind of error is that? */ | ||
665 | return NULL; | ||
666 | } | ||
667 | |||
668 | cmdlen = strlen(filename); | ||
669 | if ((cmdlen < 5) || (0 != strcmp(&filename[cmdlen - 4], ".exe"))) | ||
670 | GNUNET_asprintf(&non_const_filename, "%s.exe", filename); | ||
671 | else | ||
672 | GNUNET_asprintf(&non_const_filename, "%s", filename); | ||
673 | |||
674 | /* It could be in POSIX form, convert it to a DOS path early on */ | ||
675 | if (ERROR_SUCCESS != | ||
676 | (lRet = plibc_conv_to_win_path(non_const_filename, win_path))) | ||
677 | { | ||
678 | SetErrnoFromWinError(lRet); | ||
679 | LOG_STRERROR_FILE(GNUNET_ERROR_TYPE_ERROR, | ||
680 | "plibc_conv_to_win_path", | ||
681 | non_const_filename); | ||
682 | GNUNET_free(non_const_filename); | ||
683 | GNUNET_free(pathbuf); | ||
684 | return NULL; | ||
685 | } | ||
686 | GNUNET_free(non_const_filename); | ||
687 | non_const_filename = GNUNET_strdup(win_path); | ||
688 | /* Check that this is the full path. If it isn't, search. */ | ||
689 | /* FIXME: convert it to wchar_t and use SearchPathW? | ||
690 | * Remember: arguments to _start_process() are technically in UTF-8... | ||
691 | */ | ||
692 | if (non_const_filename[1] == ':') | ||
693 | { | ||
694 | snprintf(path, sizeof(path) / sizeof(char), "%s", non_const_filename); | ||
695 | LOG(GNUNET_ERROR_TYPE_DEBUG, | ||
696 | "Using path `%s' as-is. PATH is %s\n", | ||
697 | path, | ||
698 | ptr); | ||
699 | } | ||
700 | else if (!SearchPathA(pathbuf, | ||
701 | non_const_filename, | ||
702 | NULL, | ||
703 | sizeof(path) / sizeof(char), | ||
704 | path, | ||
705 | NULL)) | ||
706 | { | ||
707 | SetErrnoFromWinError(GetLastError()); | ||
708 | LOG_STRERROR_FILE(GNUNET_ERROR_TYPE_ERROR, | ||
709 | "SearchPath", | ||
710 | non_const_filename); | ||
711 | GNUNET_free(non_const_filename); | ||
712 | GNUNET_free(pathbuf); | ||
713 | return NULL; | ||
714 | } | ||
715 | else | ||
716 | LOG(GNUNET_ERROR_TYPE_DEBUG, "Found `%s' in PATH `%s'\n", path, pathbuf); | ||
717 | GNUNET_free(pathbuf); | ||
718 | GNUNET_free(non_const_filename); | ||
719 | |||
720 | /* Count the number of arguments */ | ||
721 | arg = (char **)argv; | ||
722 | while (*arg) | ||
723 | { | ||
724 | arg++; | ||
725 | argcount++; | ||
726 | } | ||
727 | |||
728 | /* Allocate a copy argv */ | ||
729 | non_const_argv = GNUNET_malloc(sizeof(char *) * (argcount + 1)); | ||
730 | |||
731 | /* Copy all argv strings */ | ||
732 | argcount = 0; | ||
733 | arg = (char **)argv; | ||
734 | while (*arg) | ||
735 | { | ||
736 | if (arg == argv) | ||
737 | non_const_argv[argcount] = GNUNET_strdup(path); | ||
738 | else | ||
739 | non_const_argv[argcount] = GNUNET_strdup(*arg); | ||
740 | arg++; | ||
741 | argcount++; | ||
742 | } | ||
743 | non_const_argv[argcount] = NULL; | ||
744 | |||
745 | /* Count cmd len */ | ||
746 | cmdlen = 1; | ||
747 | arg = non_const_argv; | ||
748 | while (*arg) | ||
749 | { | ||
750 | cmdlen = cmdlen + strlen(*arg) + 4; | ||
751 | arg++; | ||
752 | } | ||
753 | |||
754 | /* Allocate and create cmd */ | ||
755 | cmd = idx = GNUNET_malloc(sizeof(char) * cmdlen); | ||
756 | arg = non_const_argv; | ||
757 | while (*arg) | ||
758 | { | ||
759 | char arg_last_char = (*arg)[strlen(*arg) - 1]; | ||
760 | idx += sprintf(idx, | ||
761 | "\"%s%s\"%s", | ||
762 | *arg, | ||
763 | arg_last_char == '\\' ? "\\" : "", | ||
764 | *(arg + 1) ? " " : ""); | ||
765 | arg++; | ||
766 | } | ||
767 | |||
768 | while (argcount > 0) | ||
769 | GNUNET_free(non_const_argv[--argcount]); | ||
770 | GNUNET_free(non_const_argv); | ||
771 | |||
772 | memset(&start, 0, sizeof(start)); | ||
773 | start.cb = sizeof(start); | ||
774 | if ((pipe_stdin != NULL) || (pipe_stdout != NULL) || (std_inheritance != 0)) | ||
775 | start.dwFlags |= STARTF_USESTDHANDLES; | ||
776 | |||
777 | stdih = GetStdHandle(STD_INPUT_HANDLE); | ||
778 | GetHandleInformation(stdih, &stdif); | ||
779 | if (pipe_stdin != NULL) | ||
780 | { | ||
781 | GNUNET_DISK_internal_file_handle_( | ||
782 | GNUNET_DISK_pipe_handle(pipe_stdin, GNUNET_DISK_PIPE_END_READ), | ||
783 | &stdin_handle, | ||
784 | sizeof(HANDLE)); | ||
785 | start.hStdInput = stdin_handle; | ||
786 | } | ||
787 | else if (stdih) | ||
788 | { | ||
789 | if (std_inheritance & GNUNET_OS_INHERIT_STD_IN) | ||
790 | { | ||
791 | SetHandleInformation(stdih, HANDLE_FLAG_INHERIT, 1); | ||
792 | if (pipe_stdin == NULL) | ||
793 | start.hStdInput = stdih; | ||
794 | } | ||
795 | else | ||
796 | SetHandleInformation(stdih, HANDLE_FLAG_INHERIT, 0); | ||
797 | } | ||
798 | |||
799 | |||
800 | stdoh = GetStdHandle(STD_OUTPUT_HANDLE); | ||
801 | GetHandleInformation(stdoh, &stdof); | ||
802 | if (NULL != pipe_stdout) | ||
803 | { | ||
804 | GNUNET_DISK_internal_file_handle_( | ||
805 | GNUNET_DISK_pipe_handle(pipe_stdout, GNUNET_DISK_PIPE_END_WRITE), | ||
806 | &stdout_handle, | ||
807 | sizeof(HANDLE)); | ||
808 | start.hStdOutput = stdout_handle; | ||
809 | } | ||
810 | else if (stdoh) | ||
811 | { | ||
812 | if (std_inheritance & GNUNET_OS_INHERIT_STD_OUT) | ||
813 | { | ||
814 | SetHandleInformation(stdoh, HANDLE_FLAG_INHERIT, 1); | ||
815 | if (pipe_stdout == NULL) | ||
816 | start.hStdOutput = stdoh; | ||
817 | } | ||
818 | else | ||
819 | SetHandleInformation(stdoh, HANDLE_FLAG_INHERIT, 0); | ||
820 | } | ||
821 | |||
822 | stdeh = GetStdHandle(STD_ERROR_HANDLE); | ||
823 | GetHandleInformation(stdeh, &stdef); | ||
824 | if (stdeh) | ||
825 | { | ||
826 | if (std_inheritance & GNUNET_OS_INHERIT_STD_ERR) | ||
827 | { | ||
828 | SetHandleInformation(stdeh, HANDLE_FLAG_INHERIT, 1); | ||
829 | start.hStdError = stdeh; | ||
830 | } | ||
831 | else | ||
832 | SetHandleInformation(stdeh, HANDLE_FLAG_INHERIT, 0); | ||
833 | } | ||
834 | |||
835 | if (GNUNET_YES == pipe_control) | ||
836 | { | ||
837 | struct GNUNET_DISK_PipeHandle *childpipe; | ||
838 | childpipe = GNUNET_DISK_pipe(GNUNET_NO, GNUNET_NO, GNUNET_YES, GNUNET_NO); | ||
839 | if (NULL == childpipe) | ||
840 | return NULL; | ||
841 | childpipe_read = | ||
842 | GNUNET_DISK_pipe_detach_end(childpipe, GNUNET_DISK_PIPE_END_READ); | ||
843 | childpipe_write = | ||
844 | GNUNET_DISK_pipe_detach_end(childpipe, GNUNET_DISK_PIPE_END_WRITE); | ||
845 | GNUNET_DISK_pipe_close(childpipe); | ||
846 | if ((NULL == childpipe_read) || (NULL == childpipe_write) || | ||
847 | (GNUNET_OK != GNUNET_DISK_internal_file_handle_(childpipe_read, | ||
848 | &childpipe_read_handle, | ||
849 | sizeof(HANDLE)))) | ||
850 | { | ||
851 | if (childpipe_read) | ||
852 | GNUNET_DISK_file_close(childpipe_read); | ||
853 | if (childpipe_write) | ||
854 | GNUNET_DISK_file_close(childpipe_write); | ||
855 | GNUNET_free(cmd); | ||
856 | return NULL; | ||
857 | } | ||
858 | /* Unlike *nix variant, we don't dup the handle, so can't close | ||
859 | * filehandle right now. | ||
860 | */ | ||
861 | SetHandleInformation(childpipe_read_handle, HANDLE_FLAG_INHERIT, 1); | ||
862 | } | ||
863 | else | ||
864 | { | ||
865 | childpipe_read = NULL; | ||
866 | childpipe_write = NULL; | ||
867 | } | ||
868 | |||
869 | if (lsocks != NULL && lsocks[0] != INVALID_SOCKET) | ||
870 | { | ||
871 | lsocks_pipe = | ||
872 | GNUNET_DISK_pipe(GNUNET_YES, GNUNET_YES, GNUNET_YES, GNUNET_NO); | ||
873 | |||
874 | if (lsocks_pipe == NULL) | ||
875 | { | ||
876 | GNUNET_free(cmd); | ||
877 | GNUNET_DISK_pipe_close(lsocks_pipe); | ||
878 | if (GNUNET_YES == pipe_control) | ||
879 | { | ||
880 | GNUNET_DISK_file_close(childpipe_write); | ||
881 | GNUNET_DISK_file_close(childpipe_read); | ||
882 | } | ||
883 | return NULL; | ||
884 | } | ||
885 | lsocks_write_fd = | ||
886 | GNUNET_DISK_pipe_handle(lsocks_pipe, GNUNET_DISK_PIPE_END_WRITE); | ||
887 | GNUNET_DISK_internal_file_handle_(lsocks_write_fd, | ||
888 | &lsocks_write, | ||
889 | sizeof(HANDLE)); | ||
890 | GNUNET_DISK_internal_file_handle_( | ||
891 | GNUNET_DISK_pipe_handle(lsocks_pipe, GNUNET_DISK_PIPE_END_READ), | ||
892 | &lsocks_read, | ||
893 | sizeof(HANDLE)); | ||
894 | } | ||
895 | else | ||
896 | { | ||
897 | lsocks_pipe = NULL; | ||
898 | lsocks_write_fd = NULL; | ||
899 | } | ||
900 | |||
901 | env_off = 0; | ||
902 | if (GNUNET_YES == pipe_control) | ||
903 | { | ||
904 | GNUNET_asprintf(&our_env[env_off++], "%s=", GNUNET_OS_CONTROL_PIPE); | ||
905 | GNUNET_asprintf(&our_env[env_off++], "%p", childpipe_read_handle); | ||
906 | } | ||
907 | if ((lsocks != NULL) && (lsocks[0] != INVALID_SOCKET)) | ||
908 | { | ||
909 | /*This will tell the child that we're going to send lsocks over the pipe*/ | ||
910 | GNUNET_asprintf(&our_env[env_off++], "%s=", "GNUNET_OS_READ_LSOCKS"); | ||
911 | GNUNET_asprintf(&our_env[env_off++], "%lu", lsocks_read); | ||
912 | } | ||
913 | our_env[env_off++] = NULL; | ||
914 | env_block = CreateCustomEnvTable(our_env); | ||
915 | while (0 > env_off) | ||
916 | GNUNET_free_non_null(our_env[--env_off]); | ||
917 | |||
918 | wpath_len = 0; | ||
919 | if (NULL == | ||
920 | (wpath = | ||
921 | u8_to_u16((uint8_t *)path, 1 + strlen(path), NULL, &wpath_len))) | ||
922 | { | ||
923 | LOG(GNUNET_ERROR_TYPE_DEBUG, | ||
924 | "Failed to convert `%s' from UTF-8 to UTF-16: %d\n", | ||
925 | path, | ||
926 | errno); | ||
927 | GNUNET_free(env_block); | ||
928 | GNUNET_free(cmd); | ||
929 | if (lsocks_pipe) | ||
930 | GNUNET_DISK_pipe_close(lsocks_pipe); | ||
931 | if (GNUNET_YES == pipe_control) | ||
932 | { | ||
933 | GNUNET_DISK_file_close(childpipe_write); | ||
934 | GNUNET_DISK_file_close(childpipe_read); | ||
935 | } | ||
936 | return NULL; | ||
937 | } | ||
938 | |||
939 | wcmd_len = 0; | ||
940 | if (NULL == | ||
941 | (wcmd = u8_to_u16((uint8_t *)cmd, 1 + strlen(cmd), NULL, &wcmd_len))) | ||
942 | { | ||
943 | LOG(GNUNET_ERROR_TYPE_DEBUG, | ||
944 | "Failed to convert `%s' from UTF-8 to UTF-16: %d\n", | ||
945 | cmd, | ||
946 | errno); | ||
947 | GNUNET_free(env_block); | ||
948 | GNUNET_free(cmd); | ||
949 | free(wpath); | ||
950 | if (lsocks_pipe) | ||
951 | GNUNET_DISK_pipe_close(lsocks_pipe); | ||
952 | if (GNUNET_YES == pipe_control) | ||
953 | { | ||
954 | GNUNET_DISK_file_close(childpipe_write); | ||
955 | GNUNET_DISK_file_close(childpipe_read); | ||
956 | } | ||
957 | return NULL; | ||
958 | } | ||
959 | |||
960 | create_no_window = 0; | ||
961 | { | ||
962 | HANDLE console_input = CreateFile("CONIN$", | ||
963 | GENERIC_READ, | ||
964 | FILE_SHARE_READ | FILE_SHARE_WRITE, | ||
965 | NULL, | ||
966 | OPEN_EXISTING, | ||
967 | 0, | ||
968 | NULL); | ||
969 | if (INVALID_HANDLE_VALUE == console_input) | ||
970 | create_no_window = CREATE_NO_WINDOW; | ||
971 | else | ||
972 | CloseHandle(console_input); | ||
973 | } | ||
974 | |||
975 | bresult = CreateProcessW(wpath, | ||
976 | wcmd, | ||
977 | NULL, | ||
978 | NULL, | ||
979 | GNUNET_YES, | ||
980 | create_no_window | CREATE_SUSPENDED, | ||
981 | env_block, | ||
982 | NULL, | ||
983 | &start, | ||
984 | &proc); | ||
985 | error_code = GetLastError(); | ||
986 | |||
987 | if ((NULL == pipe_stdin) && (stdih)) | ||
988 | SetHandleInformation(stdih, HANDLE_FLAG_INHERIT, stdif); | ||
989 | |||
990 | |||
991 | if ((NULL == pipe_stdout) && (stdoh)) | ||
992 | SetHandleInformation(stdoh, HANDLE_FLAG_INHERIT, stdof); | ||
993 | |||
994 | if (stdeh) | ||
995 | SetHandleInformation(stdeh, HANDLE_FLAG_INHERIT, stdef); | ||
996 | |||
997 | if (!bresult) | ||
998 | LOG(GNUNET_ERROR_TYPE_ERROR, | ||
999 | "CreateProcess(%s, %s) failed: %lu\n", | ||
1000 | path, | ||
1001 | cmd, | ||
1002 | error_code); | ||
1003 | |||
1004 | GNUNET_free(env_block); | ||
1005 | GNUNET_free(cmd); | ||
1006 | free(wpath); | ||
1007 | free(wcmd); | ||
1008 | if (GNUNET_YES == pipe_control) | ||
1009 | { | ||
1010 | GNUNET_DISK_file_close(childpipe_read); | ||
1011 | } | ||
1012 | |||
1013 | if (!bresult) | ||
1014 | { | ||
1015 | if (GNUNET_YES == pipe_control) | ||
1016 | { | ||
1017 | GNUNET_DISK_file_close(childpipe_write); | ||
1018 | } | ||
1019 | if (NULL != lsocks) | ||
1020 | GNUNET_DISK_pipe_close(lsocks_pipe); | ||
1021 | SetErrnoFromWinError(error_code); | ||
1022 | return NULL; | ||
1023 | } | ||
1024 | |||
1025 | gnunet_proc = GNUNET_new(struct GNUNET_OS_Process); | ||
1026 | gnunet_proc->pid = proc.dwProcessId; | ||
1027 | gnunet_proc->handle = proc.hProcess; | ||
1028 | gnunet_proc->control_pipe = childpipe_write; | ||
1029 | |||
1030 | CreateThread(NULL, 64000, &child_wait_thread, (void *)gnunet_proc, 0, NULL); | ||
1031 | |||
1032 | ResumeThread(proc.hThread); | ||
1033 | CloseHandle(proc.hThread); | ||
1034 | |||
1035 | if ((NULL == lsocks) || (INVALID_SOCKET == lsocks[0])) | ||
1036 | return gnunet_proc; | ||
1037 | |||
1038 | GNUNET_DISK_pipe_close_end(lsocks_pipe, GNUNET_DISK_PIPE_END_READ); | ||
1039 | |||
1040 | /* This is a replacement for "goto error" that doesn't use goto */ | ||
1041 | fail = 1; | ||
1042 | do | ||
1043 | { | ||
1044 | ssize_t wrote; | ||
1045 | uint64_t size; | ||
1046 | uint64_t count; | ||
1047 | unsigned int i; | ||
1048 | |||
1049 | /* Tell the number of sockets */ | ||
1050 | for (count = 0; lsocks && lsocks[count] != INVALID_SOCKET; count++) | ||
1051 | ; | ||
1052 | |||
1053 | wrote = GNUNET_DISK_file_write(lsocks_write_fd, &count, sizeof(count)); | ||
1054 | if (sizeof(count) != wrote) | ||
1055 | { | ||
1056 | GNUNET_log(GNUNET_ERROR_TYPE_ERROR, | ||
1057 | "Failed to write %u count bytes to the child: %lu\n", | ||
1058 | sizeof(count), | ||
1059 | GetLastError()); | ||
1060 | break; | ||
1061 | } | ||
1062 | for (i = 0; lsocks && lsocks[i] != INVALID_SOCKET; i++) | ||
1063 | { | ||
1064 | WSAPROTOCOL_INFOA pi; | ||
1065 | /* Get a socket duplication info */ | ||
1066 | if (SOCKET_ERROR == | ||
1067 | WSADuplicateSocketA(lsocks[i], gnunet_proc->pid, &pi)) | ||
1068 | { | ||
1069 | GNUNET_log(GNUNET_ERROR_TYPE_ERROR, | ||
1070 | "Failed to duplicate an socket[%u]: %lu\n", | ||
1071 | i, | ||
1072 | GetLastError()); | ||
1073 | break; | ||
1074 | } | ||
1075 | /* Synchronous I/O is not nice, but we can't schedule this: | ||
1076 | * lsocks will be closed/freed by the caller soon, and until | ||
1077 | * the child creates a duplicate, closing a socket here will | ||
1078 | * close it for good. | ||
1079 | */ | ||
1080 | /* Send the size of the structure | ||
1081 | * (the child might be built with different headers...) | ||
1082 | */ | ||
1083 | size = sizeof(pi); | ||
1084 | wrote = GNUNET_DISK_file_write(lsocks_write_fd, &size, sizeof(size)); | ||
1085 | if (sizeof(size) != wrote) | ||
1086 | { | ||
1087 | GNUNET_log(GNUNET_ERROR_TYPE_ERROR, | ||
1088 | "Failed to write %u size[%u] bytes to the child: %lu\n", | ||
1089 | sizeof(size), | ||
1090 | i, | ||
1091 | GetLastError()); | ||
1092 | break; | ||
1093 | } | ||
1094 | /* Finally! Send the data */ | ||
1095 | wrote = GNUNET_DISK_file_write(lsocks_write_fd, &pi, sizeof(pi)); | ||
1096 | if (sizeof(pi) != wrote) | ||
1097 | { | ||
1098 | GNUNET_log(GNUNET_ERROR_TYPE_ERROR, | ||
1099 | "Failed to write %u socket[%u] bytes to the child: %lu\n", | ||
1100 | sizeof(pi), | ||
1101 | i, | ||
1102 | GetLastError()); | ||
1103 | break; | ||
1104 | } | ||
1105 | } | ||
1106 | /* This will block us until the child makes a final read or closes | ||
1107 | * the pipe (hence no 'wrote' check), since we have to wait for it | ||
1108 | * to duplicate the last socket, before we return and start closing | ||
1109 | * our own copies) | ||
1110 | */ | ||
1111 | wrote = GNUNET_DISK_file_write(lsocks_write_fd, &count, sizeof(count)); | ||
1112 | fail = 0; | ||
1113 | } | ||
1114 | while (fail); | ||
1115 | |||
1116 | GNUNET_DISK_file_sync(lsocks_write_fd); | ||
1117 | GNUNET_DISK_pipe_close(lsocks_pipe); | ||
1118 | |||
1119 | if (fail) | ||
1120 | { | ||
1121 | /* If we can't pass on the socket(s), the child will block forever, | ||
1122 | * better put it out of its misery. | ||
1123 | */ | ||
1124 | SafeTerminateProcess(gnunet_proc->handle, 0, 0); | ||
1125 | CloseHandle(gnunet_proc->handle); | ||
1126 | if (NULL != gnunet_proc->control_pipe) | ||
1127 | GNUNET_DISK_file_close(gnunet_proc->control_pipe); | ||
1128 | GNUNET_free(gnunet_proc); | ||
1129 | return NULL; | ||
1130 | } | ||
1131 | return gnunet_proc; | ||
1132 | #endif | ||
1133 | } | 591 | } |
1134 | 592 | ||
1135 | 593 | ||
@@ -1439,7 +897,6 @@ process_status(struct GNUNET_OS_Process *proc, | |||
1439 | unsigned long *code, | 897 | unsigned long *code, |
1440 | int options) | 898 | int options) |
1441 | { | 899 | { |
1442 | #ifndef MINGW | ||
1443 | int status; | 900 | int status; |
1444 | int ret; | 901 | int ret; |
1445 | 902 | ||
@@ -1488,53 +945,6 @@ process_status(struct GNUNET_OS_Process *proc, | |||
1488 | *type = GNUNET_OS_PROCESS_UNKNOWN; | 945 | *type = GNUNET_OS_PROCESS_UNKNOWN; |
1489 | *code = 0; | 946 | *code = 0; |
1490 | } | 947 | } |
1491 | #else | ||
1492 | #ifndef WNOHANG | ||
1493 | #define WNOHANG 42 /* just a flag for W32, purely internal at this point */ | ||
1494 | #endif | ||
1495 | |||
1496 | HANDLE h; | ||
1497 | DWORD c, error_code, ret; | ||
1498 | |||
1499 | h = proc->handle; | ||
1500 | ret = proc->pid; | ||
1501 | if (h == NULL || ret == 0) | ||
1502 | { | ||
1503 | LOG(GNUNET_ERROR_TYPE_WARNING, | ||
1504 | "Invalid process information {%d, %08X}\n", | ||
1505 | ret, | ||
1506 | h); | ||
1507 | return GNUNET_SYSERR; | ||
1508 | } | ||
1509 | if (h == NULL) | ||
1510 | h = GetCurrentProcess(); | ||
1511 | |||
1512 | if (WNOHANG != options) | ||
1513 | { | ||
1514 | if (WAIT_OBJECT_0 != WaitForSingleObject(h, INFINITE)) | ||
1515 | { | ||
1516 | SetErrnoFromWinError(GetLastError()); | ||
1517 | return GNUNET_SYSERR; | ||
1518 | } | ||
1519 | } | ||
1520 | SetLastError(0); | ||
1521 | ret = GetExitCodeProcess(h, &c); | ||
1522 | error_code = GetLastError(); | ||
1523 | if (ret == 0 || error_code != NO_ERROR) | ||
1524 | { | ||
1525 | SetErrnoFromWinError(error_code); | ||
1526 | LOG_STRERROR(GNUNET_ERROR_TYPE_WARNING, "GetExitCodeProcess"); | ||
1527 | return GNUNET_SYSERR; | ||
1528 | } | ||
1529 | if (STILL_ACTIVE == c) | ||
1530 | { | ||
1531 | *type = GNUNET_OS_PROCESS_RUNNING; | ||
1532 | *code = 0; | ||
1533 | return GNUNET_NO; | ||
1534 | } | ||
1535 | *type = GNUNET_OS_PROCESS_EXITED; | ||
1536 | *code = c; | ||
1537 | #endif | ||
1538 | 948 | ||
1539 | return GNUNET_OK; | 949 | return GNUNET_OK; |
1540 | } | 950 | } |
@@ -1589,7 +999,6 @@ GNUNET_OS_process_wait_status(struct GNUNET_OS_Process *proc, | |||
1589 | int | 999 | int |
1590 | GNUNET_OS_process_wait(struct GNUNET_OS_Process *proc) | 1000 | GNUNET_OS_process_wait(struct GNUNET_OS_Process *proc) |
1591 | { | 1001 | { |
1592 | #ifndef MINGW | ||
1593 | pid_t pid = proc->pid; | 1002 | pid_t pid = proc->pid; |
1594 | pid_t ret; | 1003 | pid_t ret; |
1595 | 1004 | ||
@@ -1601,28 +1010,6 @@ GNUNET_OS_process_wait(struct GNUNET_OS_Process *proc) | |||
1601 | return GNUNET_SYSERR; | 1010 | return GNUNET_SYSERR; |
1602 | } | 1011 | } |
1603 | return GNUNET_OK; | 1012 | return GNUNET_OK; |
1604 | #else | ||
1605 | HANDLE h; | ||
1606 | |||
1607 | h = proc->handle; | ||
1608 | if (NULL == h) | ||
1609 | { | ||
1610 | LOG(GNUNET_ERROR_TYPE_WARNING, | ||
1611 | "Invalid process information {%d, %08X}\n", | ||
1612 | proc->pid, | ||
1613 | h); | ||
1614 | return GNUNET_SYSERR; | ||
1615 | } | ||
1616 | if (NULL == h) | ||
1617 | h = GetCurrentProcess(); | ||
1618 | |||
1619 | if (WAIT_OBJECT_0 != WaitForSingleObject(h, INFINITE)) | ||
1620 | { | ||
1621 | SetErrnoFromWinError(GetLastError()); | ||
1622 | return GNUNET_SYSERR; | ||
1623 | } | ||
1624 | return GNUNET_OK; | ||
1625 | #endif | ||
1626 | } | 1013 | } |
1627 | 1014 | ||
1628 | 1015 | ||