Exemple #1
0
int 
main(int argc,char **argv) {

  struct cmdlineInfo cmdline;
  unsigned int i;

  pbm_init(&argc, argv);

  parseCommandLine(argc, argv, &cmdline);

  sent_xon = FALSE;

  for (i = 0; i < cmdline.nFiles; ++i) {
      FILE *ifP;
      pm_message("opening '%s'", cmdline.inputFile[i]);
      ifP = pm_openr(cmdline.inputFile[i]);
      process_handle(ifP, cmdline.graph_mode, cmdline.passes);
      pm_close(ifP);
  }

  free(cmdline.inputFile);

  return 0;
}
int launch_server(const std::string& socket_spec) {
#if defined(_WIN32)
    /* we need to start the server in the background                    */
    /* we create a PIPE that will be used to wait for the server's "OK" */
    /* message since the pipe handles must be inheritable, we use a     */
    /* security attribute                                               */
    SECURITY_ATTRIBUTES   sa;
    sa.nLength = sizeof(sa);
    sa.lpSecurityDescriptor = NULL;
    sa.bInheritHandle = TRUE;

    // Redirect stdin to Windows /dev/null. If we instead pass an original
    // stdin/stdout/stderr handle and it is a console handle, when the adb
    // server starts up, the C Runtime will see a console handle for a process
    // that isn't connected to a console and it will configure
    // stdin/stdout/stderr to be closed. At that point, freopen() could be used
    // to reopen stderr/out, but it would take more massaging to fixup the file
    // descriptor number that freopen() uses. It's simplest to avoid all of this
    // complexity by just redirecting stdin to `nul' and then the C Runtime acts
    // as expected.
    unique_handle   nul_read(CreateFileW(L"nul", GENERIC_READ,
            FILE_SHARE_READ | FILE_SHARE_WRITE, &sa, OPEN_EXISTING,
            FILE_ATTRIBUTE_NORMAL, NULL));
    if (nul_read.get() == INVALID_HANDLE_VALUE) {
        fprintf(stderr, "Cannot open 'nul': %s\n",
                android::base::SystemErrorCodeToString(GetLastError()).c_str());
        return -1;
    }

    // Create pipes with non-inheritable read handle, inheritable write handle. We need to connect
    // the subprocess to pipes instead of just letting the subprocess inherit our existing
    // stdout/stderr handles because a DETACHED_PROCESS cannot write to a console that it is not
    // attached to.
    unique_handle   ack_read, ack_write;
    if (!_create_anonymous_pipe(&ack_read, &ack_write, &sa)) {
        return -1;
    }
    unique_handle   stdout_read, stdout_write;
    if (!_create_anonymous_pipe(&stdout_read, &stdout_write, &sa)) {
        return -1;
    }
    unique_handle   stderr_read, stderr_write;
    if (!_create_anonymous_pipe(&stderr_read, &stderr_write, &sa)) {
        return -1;
    }

    /* Some programs want to launch an adb command and collect its output by
     * calling CreateProcess with inheritable stdout/stderr handles, then
     * using read() to get its output. When this happens, the stdout/stderr
     * handles passed to the adb client process will also be inheritable.
     * When starting the adb server here, care must be taken to reset them
     * to non-inheritable.
     * Otherwise, something bad happens: even if the adb command completes,
     * the calling process is stuck while read()-ing from the stdout/stderr
     * descriptors, because they're connected to corresponding handles in the
     * adb server process (even if the latter never uses/writes to them).
     * Note that even if we don't pass these handles in the STARTUPINFO struct,
     * if they're marked inheritable, they're still inherited, requiring us to
     * deal with this.
     *
     * If we're still having problems with inheriting random handles in the
     * future, consider using PROC_THREAD_ATTRIBUTE_HANDLE_LIST to explicitly
     * specify which handles should be inherited: http://blogs.msdn.com/b/oldnewthing/archive/2011/12/16/10248328.aspx
     *
     * Older versions of Windows return console pseudo-handles that cannot be
     * made non-inheritable, so ignore those failures.
     */
    _try_make_handle_noninheritable(GetStdHandle(STD_INPUT_HANDLE));
    _try_make_handle_noninheritable(GetStdHandle(STD_OUTPUT_HANDLE));
    _try_make_handle_noninheritable(GetStdHandle(STD_ERROR_HANDLE));

    STARTUPINFOW    startup;
    ZeroMemory( &startup, sizeof(startup) );
    startup.cb = sizeof(startup);
    startup.hStdInput  = nul_read.get();
    startup.hStdOutput = stdout_write.get();
    startup.hStdError  = stderr_write.get();
    startup.dwFlags    = STARTF_USESTDHANDLES;

    // Verify that the pipe_write handle value can be passed on the command line
    // as %d and that the rest of adb code can pass it around in an int.
    const int ack_write_as_int = cast_handle_to_int(ack_write.get());
    if (cast_int_to_handle(ack_write_as_int) != ack_write.get()) {
        // If this fires, either handle values are larger than 32-bits or else
        // there is a bug in our casting.
        // https://msdn.microsoft.com/en-us/library/windows/desktop/aa384203%28v=vs.85%29.aspx
        fprintf(stderr, "Cannot fit pipe handle value into 32-bits: 0x%p\n",
                ack_write.get());
        return -1;
    }

    // get path of current program
    WCHAR       program_path[MAX_PATH];
    const DWORD module_result = GetModuleFileNameW(NULL, program_path,
                                                   arraysize(program_path));
    if ((module_result >= arraysize(program_path)) || (module_result == 0)) {
        // String truncation or some other error.
        fprintf(stderr, "Cannot get executable path: %s\n",
                android::base::SystemErrorCodeToString(GetLastError()).c_str());
        return -1;
    }

    WCHAR   args[64];
    snwprintf(args, arraysize(args), L"adb -L %s fork-server server --reply-fd %d",
              socket_spec.c_str(), ack_write_as_int);

    PROCESS_INFORMATION   pinfo;
    ZeroMemory(&pinfo, sizeof(pinfo));

    if (!CreateProcessW(
            program_path,                              /* program path  */
            args,
                                    /* the fork-server argument will set the
                                       debug = 2 in the child           */
            NULL,                   /* process handle is not inheritable */
            NULL,                    /* thread handle is not inheritable */
            TRUE,                          /* yes, inherit some handles */
            DETACHED_PROCESS, /* the new process doesn't have a console */
            NULL,                     /* use parent's environment block */
            NULL,                    /* use parent's starting directory */
            &startup,                 /* startup info, i.e. std handles */
            &pinfo )) {
        fprintf(stderr, "Cannot create process: %s\n",
                android::base::SystemErrorCodeToString(GetLastError()).c_str());
        return -1;
    }

    unique_handle   process_handle(pinfo.hProcess);
    pinfo.hProcess = NULL;

    // Close handles that we no longer need to complete the rest.
    CloseHandle(pinfo.hThread);
    pinfo.hThread = NULL;

    nul_read.reset();
    ack_write.reset();
    stdout_write.reset();
    stderr_write.reset();

    // Start threads to read from subprocess stdout/stderr and write to ours to make subprocess
    // errors easier to diagnose. Note that the threads internally create inheritable handles, but
    // that is ok because we've already spawned the subprocess.

    // In the past, reading from a pipe before the child process's C Runtime
    // started up and called GetFileType() caused a hang: http://blogs.msdn.com/b/oldnewthing/archive/2011/12/02/10243553.aspx#10244216
    // This is reportedly fixed in Windows Vista: https://support.microsoft.com/en-us/kb/2009703
    // I was unable to reproduce the problem on Windows XP. It sounds like a
    // Windows Update may have fixed this: https://www.duckware.com/tech/peeknamedpipe.html
    unique_handle   stdout_thread(reinterpret_cast<HANDLE>(
            _beginthreadex(NULL, 0, _redirect_stdout_thread, stdout_read.get(),
                           0, NULL)));
    if (stdout_thread.get() == nullptr) {
        fprintf(stderr, "Cannot create thread: %s\n", strerror(errno));
        return -1;
    }
    stdout_read.release();  // Transfer ownership to new thread

    unique_handle   stderr_thread(reinterpret_cast<HANDLE>(
            _beginthreadex(NULL, 0, _redirect_stderr_thread, stderr_read.get(),
                           0, NULL)));
    if (stderr_thread.get() == nullptr) {
        fprintf(stderr, "Cannot create thread: %s\n", strerror(errno));
        return -1;
    }
    stderr_read.release();  // Transfer ownership to new thread

    bool    got_ack = false;

    // Wait for the "OK\n" message, for the pipe to be closed, or other error.
    {
        char    temp[3];
        DWORD   count = 0;

        if (ReadFile(ack_read.get(), temp, sizeof(temp), &count, NULL)) {
            const CHAR  expected[] = "OK\n";
            const DWORD expected_length = arraysize(expected) - 1;
            if (count == expected_length &&
                memcmp(temp, expected, expected_length) == 0) {
                got_ack = true;
            } else {
                fprintf(stderr, "ADB server didn't ACK\n");
            }
        } else {
            const DWORD err = GetLastError();
            // If the ACK was not written and the process exited, GetLastError()
            // is probably ERROR_BROKEN_PIPE, in which case that info is not
            // useful to the user.
            fprintf(stderr, "could not read ok from ADB Server%s\n",
                    err == ERROR_BROKEN_PIPE ? "" :
                    android::base::StringPrintf(": %s",
                            android::base::SystemErrorCodeToString(err).c_str()).c_str());
        }
    }

    // Always try to wait a bit for threads reading stdout/stderr to finish.
    // If the process started ok, it should close the pipes causing the threads
    // to finish. If the process had an error, it should exit, also causing
    // the pipes to be closed. In that case we want to read all of the output
    // and write it out so that the user can diagnose failures.
    const DWORD     thread_timeout_ms = 15 * 1000;
    const HANDLE    threads[] = { stdout_thread.get(), stderr_thread.get() };
    const DWORD     wait_result = WaitForMultipleObjects(arraysize(threads),
            threads, TRUE, thread_timeout_ms);
    if (wait_result == WAIT_TIMEOUT) {
        // Threads did not finish after waiting a little while. Perhaps the
        // server didn't close pipes, or it is hung.
        fprintf(stderr, "Timed-out waiting for threads to finish reading from "
                "ADB Server\n");
        // Process handles are signaled when the process exits, so if we wait
        // on the handle for 0 seconds and it returns 'timeout', that means that
        // the process is still running.
        if (WaitForSingleObject(process_handle.get(), 0) == WAIT_TIMEOUT) {
            // We could TerminateProcess(), but that seems somewhat presumptive.
            fprintf(stderr, "ADB Server is running: process id %lu\n",
                    pinfo.dwProcessId);
        }
        return -1;
    }

    if (wait_result != WAIT_OBJECT_0) {
        fprintf(stderr, "Unexpected result waiting for threads: %lu: %s\n",
                wait_result, android::base::SystemErrorCodeToString(GetLastError()).c_str());
        return -1;
    }

    // For now ignore the thread exit codes and assume they worked properly.

    if (!got_ack) {
        return -1;
    }
#else /* !defined(_WIN32) */
    // set up a pipe so the child can tell us when it is ready.
    // fd[0] will be parent's end, and the child will write on fd[1]
    int fd[2];
    if (pipe(fd)) {
        fprintf(stderr, "pipe failed in launch_server, errno: %d\n", errno);
        return -1;
    }

    std::string path = android::base::GetExecutablePath();

    pid_t pid = fork();
    if (pid < 0) return -1;

    if (pid == 0) {
        // child side of the fork

        adb_close(fd[0]);

        char reply_fd[30];
        snprintf(reply_fd, sizeof(reply_fd), "%d", fd[1]);
        // child process
        int result = execl(path.c_str(), "adb", "-L", socket_spec.c_str(), "fork-server", "server",
                           "--reply-fd", reply_fd, NULL);
        // this should not return
        fprintf(stderr, "OOPS! execl returned %d, errno: %d\n", result, errno);
    } else  {
        // parent side of the fork

        char  temp[3];

        temp[0] = 'A'; temp[1] = 'B'; temp[2] = 'C';
        // wait for the "OK\n" message
        adb_close(fd[1]);
        int ret = adb_read(fd[0], temp, 3);
        int saved_errno = errno;
        adb_close(fd[0]);
        if (ret < 0) {
            fprintf(stderr, "could not read ok from ADB Server, errno = %d\n", saved_errno);
            return -1;
        }
        if (ret != 3 || temp[0] != 'O' || temp[1] != 'K' || temp[2] != '\n') {
            fprintf(stderr, "ADB server didn't ACK\n" );
            return -1;
        }
    }
#endif /* !defined(_WIN32) */
    return 0;
}
Exemple #3
0
/**
 * Process incoming packets. 
 */
int inic_data_loop(void)
{
		cvm_common_wqe_t *swp = NULL;
		cvm_tcp_in_endpoints_t conn;
		cvm_tcp_tcphdr_t *th = NULL;
		cvm_ip_ip_t *ih = NULL;
		cvmx_sysinfo_t *sys_info_ptr = cvmx_sysinfo_get();
		uint64_t cpu_clock_hz = sys_info_ptr->cpu_clock_hz;
		uint64_t tick_cycle = cvmx_get_cycle();
		uint64_t tick_step;
		uint32_t idle_processing_interval_ticks = (CVM_COMMON_IDLE_PROCESSING_INTERVAL)*(1000*1000)/(CVM_COMMON_TICK_LEN_US);
		uint32_t idle_processing_last_ticks = 0;
#ifdef INET6
		struct cvm_ip6_ip6_hdr *ip6 = NULL;
#ifdef CVM_ENET_TUNNEL
		struct cvm_ip6_ip6_hdr *i6h = NULL;
#endif
#endif


#ifdef CVM_CLI_APP
		uint64_t idle_cycle_start_value;
#endif

		/* for the simulator */
		if (cpu_clock_hz == 0)
		{
				cpu_clock_hz = 333000000;
		}

		tick_step = (CVM_COMMON_TICK_LEN_US * cpu_clock_hz) / 1000000;
		cvm_debug_print_interval = cpu_clock_hz;

#ifndef REAL_HW
		/* for the simulator, set the debug interval to be 3M cycles */
		cvm_debug_print_interval = 3000000;
#endif

#ifdef DUTY_CYCLE
		start_cycle = cvmx_get_cycle();
		process_count = 0;
#endif

		if (cvmx_coremask_first_core(coremask_data)) 
		{
				/* Initiate a timer transaction for arp entry timeouts */
				//if(cvm_enet_arp_timeout_init() != CVMX_TIM_STATUS_SUCCESS)
				//{
				//		printf("Failed init of cvm_ip_arp_timeout_init\n");
				//}
		}

#if defined(CVM_COMBINED_APP_STACK)
		/* Flush the packets sent by main_global and main_local */
		/*
		printf("before cvm_send_packet () \n ");
		if (out_swp)
		{
				cvm_send_packet ();
		}
		printf("after cvm_send_packet () \n ");
		*/
		uint64_t app_timeout = cvmx_get_cycle ();
#endif




		/* start the main loop */
		while (1)
		{


#ifdef DUTY_CYCLE
				end_cycle = cvmx_get_cycle();

				/* check the wrap around case */
				if (end_cycle < start_cycle) end_cycle += cpu_clock_hz;

				if ((end_cycle - start_cycle) > cvm_debug_print_interval)
				{
						inic_do_per_second_duty_cycle_processing();
				}
#endif /* DUTY_CYCLE */

				cvmx_pow_work_request_async_nocheck(CVMX_SCR_WORK, 1);

				/* update the ticks variable */
				while (cvmx_get_cycle() - tick_cycle > tick_step)
				{
						tick_cycle += tick_step;
						cvm_tcp_ticks++;
						if (!(cvm_tcp_ticks & 0x1f)) CVM_COMMON_HISTORY_SET_CYCLE();
				}


				/* do common idle processing */
				if ( (cvm_tcp_ticks - idle_processing_last_ticks) > idle_processing_interval_ticks)
				{
						if (cvmx_coremask_first_core(coremask_data)) 
						{
								cvm_common_do_idle_processing();
						}

						idle_processing_last_ticks = cvm_tcp_ticks;
				}


#ifdef CVM_CLI_APP
				idle_cycle_start_value = cvmx_get_cycle();
#endif

				/* get work entry */
				swp = (cvm_common_wqe_t *)cvmx_pow_work_response_async(CVMX_SCR_WORK);
				if (swp == NULL)
				{
						idle_counter++;

						if(core_id == highest_core_id)
						{
								cvm_enet_check_link_status();
						}

#ifdef CVM_CLI_APP
						cvmx_fau_atomic_add64(core_idle_cycles[core_id], (cvmx_get_cycle()-idle_cycle_start_value) );
#endif
						continue;
				}

				CVM_COMMON_EXTRA_STATS_ADD64 (CVM_FAU_REG_WQE_RCVD, 1);

#ifdef WORK_QUEUE_ENTRY_SIZE_128 // {
				CVMX_PREFETCH0(swp);
#else
				/* Prefetch work-queue entry */
				CVMX_PREFETCH0(swp);
				CVMX_PREFETCH128(swp);
#endif // WORK_QUEUE_ENTRY_SIZE_128 }

				out_swp = 0;
				out_swp_tail = 0;


#ifdef DUTY_CYCLE
				/* we are about to start processing the packet - remember the cycle count */
				process_start_cycle = cvmx_get_cycle();
#endif


				/* Short cut the common case */
				if (cvmx_likely(swp->hw_wqe.unused == 0))
				{
						goto packet_from_the_wire;
				}
				printf("Get work with unused is %X\n", swp->hw_wqe.unused);

				{
						{

packet_from_the_wire:

#if CVM_PKO_DONTFREE
								swp->hw_wqe.packet_ptr.s.i = 0;
#endif

#ifdef SANITY_CHECKS
								/* we have a work queue entry - do input sanity checks */
								ret = cvm_common_input_sanity_and_buffer_count_update(swp);
#endif

								if (cvmx_unlikely(swp->hw_wqe.word2.s.rcv_error))
								{
										goto discard_swp; /* Receive error */
								}

#ifndef WORK_QUEUE_ENTRY_SIZE_128 // {
								{
										/* Make sure pre-fetch completed */
										uint64_t dp = *(volatile uint64_t*)&swp->next;
								}
#endif // WORK_QUEUE_ENTRY_SIZE_128 }

								{
										/* Initialize SW portion of the work-queue entry */
										uint64_t *dptr = (uint64_t*)(&swp->next);
										dptr[0] = 0;
										dptr[1] = 0;
										dptr[2] = 0;
										dptr[3] = 0;
								}

								if(cvmx_unlikely(swp->hw_wqe.word2.s.not_IP))
								{
										goto output;
								}

								/* Shortcut classification to avoid multiple lookups */
								if(
#ifndef INET6
												swp->hw_wqe.word2.s.is_v6 || 
#endif
												swp->hw_wqe.word2.s.is_bcast 
#ifndef INET6
												|| swp->hw_wqe.word2.s.is_mcast
#endif
								  )
								{
										goto discard_swp; /* Receive error */
								}


								/* Packet is unicast IPv4, without L2 errors */
								/* (All IP exceptions are dropped.  This currently includes
								 *  IPv4 options and IPv6 extension headers.)
								 */
								if(cvmx_unlikely(swp->hw_wqe.word2.s.IP_exc))
								{
										goto discard_swp;
								}

								/* Packet is Ipv4 (and no IP exceptions) */
								if (cvmx_unlikely(swp->hw_wqe.word2.s.is_frag || !swp->hw_wqe.word2.s.tcp_or_udp))
								{
										goto output;
								}

#ifdef ANVL_RFC_793_COMPLIANCE
								/* RFC 793 says that:
								   - We should send a RST out when we get a packet with FIN set 
								   without the ACK bit set in the flags field. 
								   - We should send a RST out when we get a packet with no flag set.
								   Hence, let TCP stack handle these conditions.
								 */
								if (cvmx_unlikely(swp->hw_wqe.word2.s.L4_error &&
														(cvmx_pip_l4_err_t)(swp->hw_wqe.word2.s.err_code != CVMX_PIP_TCP_FLG8_ERR) &&
														(cvmx_pip_l4_err_t)(swp->hw_wqe.word2.s.err_code != CVMX_PIP_TCP_FLG9_ERR)))
#else
										if (cvmx_unlikely(swp->hw_wqe.word2.s.L4_error))
#endif
										{
												cvm_tcp_handle_error(swp);
												goto discard_swp;
										}

								/* Packet is not fragmented, TCP/UDP, no IP exceptions/L4 errors */
								/* We can try an L4 lookup now, but we need all the information */
								ih = ((cvm_ip_ip_t *)&(swp->hw_wqe.packet_data[CVM_COMMON_PD_ALIGN]));

								if (!swp->hw_wqe.word2.s.is_v6)
								{
										/* for IPv4, we must subtract CVM_COMMON_PD_ALIGN rom tcp_offset to get the offset in the mbuf */
										swp->l4_offset = ((uint16_t)(ih->ip_hl) << 2) + CVM_COMMON_PD_ALIGN;
										swp->l4_prot = ih->ip_p;
								}
#ifdef INET6
								else
								{
										ip6 = (struct cvm_ip6_ip6_hdr *) &swp->hw_wqe.packet_data[CVM_COMMON_IP6_PD_ALIGN];

										CVM_COMMON_DBG_MSG (CVM_COMMON_DBG_LVL_5, 
														"%s: %d Packet trace Src: %s/%d Dest: %s/%d prot: %d len: %d\n", 
														__FUNCTION__, __LINE__, 
														cvm_ip6_ip6_sprintf (&ip6->ip6_dst), conn.ie_fport, 
														cvm_ip6_ip6_sprintf (&ip6->ip6_src), conn.ie_lport,
														swp->l4_prot, swp->hw_wqe.len);
										/* for IPv4, we must subtract CVM_COMMON_PD_ALIGN rom tcp_offset to get the offset in the mbuf */
										swp->l4_offset = CVM_IP6_IP6_HDRLEN;
										swp->l4_prot = ip6->ip6_ctlun.ip6_un1.ip6_un1_nxt;

								}
#endif

								th = ((cvm_tcp_tcphdr_t *)&(swp->hw_wqe.packet_data[swp->l4_offset]));

								/* check if it is a TCP packet */
								if (swp->l4_prot == CVM_IP_IPPROTO_TCP)
								{
										process_handle(swp);
#ifdef INET6
										if (!swp->hw_wqe.word2.s.is_v6)
#endif
										{
												CVM_TCP_TCP_DUMP ((void*)ih);

												/* assume IPv4 for now */
												conn.ie_laddr = ih->ip_dst.s_addr;
												conn.ie_faddr = ih->ip_src.s_addr;
												conn.ie_lport = th->th_dport;
												conn.ie_fport = th->th_sport;

										}
#ifdef INET6
										else
										{
												/* assume IPv4 for now */
												memcpy (&conn.ie6_laddr, &ip6->ip6_dst, sizeof (struct cvm_ip6_in6_addr));
												memcpy (&conn.ie6_faddr, &ip6->ip6_src, sizeof (struct cvm_ip6_in6_addr));
												conn.ie_lport = th->th_dport;
												conn.ie_fport = th->th_sport;

												/* do a TCP lookup */
												swp->tcb = cvm_tcp6_lookup (swp);

												CVM_COMMON_DBG_MSG (CVM_COMMON_DBG_LVL_5, "%s: %d TCPv6 lookup Src: %s/%d Dest: %s/%d ret_tcb: 0x%llx\n", 
																__FUNCTION__, __LINE__, 
																cvm_ip6_ip6_sprintf ((cvm_ip6_in6_addr_t *) &conn.ie6_faddr), conn.ie_fport, 
																cvm_ip6_ip6_sprintf ((cvm_ip6_in6_addr_t *) &conn.ie6_laddr), conn.ie_lport, 
																CAST64(swp->tcb));
										}
#endif // INET6
								}


								goto output;
						} /* packet from wire */
				} /* switch */


output:
				CVMX_SYNCWS;

				/* Send packet out */
				if (out_swp)
				{
						cvm_send_packet();
				}

				if(swp != NULL)
				{
						S3_send_packet((cvmx_wqe_t *)swp);
						swp = NULL;
				}
#ifdef DUTY_CYCLE
				process_end_cycle = cvmx_get_cycle();
				process_count += (process_end_cycle - process_start_cycle);
#endif
		}

		return (0);


discard_swp:
		/* Free the chained buffers */
		cvm_common_packet_free(swp);

		/* Free the work queue entry */
		cvm_common_free_fpa_buffer(swp, CVMX_FPA_WQE_POOL, CVMX_FPA_WQE_POOL_SIZE / CVMX_CACHE_LINE_SIZE);
		swp = NULL;
		goto output;

} /* inic_data_loop */