Eine aufbereitete Darstellung der Quelle

 
     
 
 
Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 

Benutzer

Quelle  test_cloexec.c

  Sprache: C
 

/*-------------------------------------------------------------------------
 *
 * test_cloexec.c
 *  Test O_CLOEXEC flag handling on Windows
 *
 * This program tests that:
 * 1. File handles opened with O_CLOEXEC are NOT inherited by child processes
 * 2. File handles opened without O_CLOEXEC ARE inherited by child processes
 *
 * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group
 *
 *-------------------------------------------------------------------------
 */


#include "postgres.h"

#include <fcntl.h>
#include <sys/stat.h>

#ifdef WIN32
#include <windows.h>
#endif

#include "common/file_utils.h"
#include "port.h"

#ifdef WIN32
static void run_parent_tests(const char *testfile1, const char *testfile2);
static void run_child_tests(const char *handle1_str, const char *handle2_str);
static bool try_write_to_handle(HANDLE h, const char *label);
#endif

int
main(int argc, char *argv[])
{
 /* Windows-only test */
#ifndef WIN32
 fprintf(stderr, "This test only runs on Windows\n");
 return 0;
#else
 char  testfile1[MAXPGPATH];
 char  testfile2[MAXPGPATH];

 if (argc == 3)
 {
  /*
   * Child mode: receives two handle values as hex strings and attempts
   * to write to them.
 */

  run_child_tests(argv[1], argv[2]);
  return 0;
 }
 else if (argc == 1)
 {
  /* Parent mode: opens files and spawns child */
  snprintf(testfile1, sizeof(testfile1), "test_cloexec_1_%d.tmp", (int) getpid());
  snprintf(testfile2, sizeof(testfile2), "test_cloexec_2_%d.tmp", (int) getpid());

  run_parent_tests(testfile1, testfile2);

  /* Clean up test files */
  unlink(testfile1);
  unlink(testfile2);

  return 0;
 }
 else
 {
  fprintf(stderr, "Usage: %s [handle1_hex handle2_hex]\n", argv[0]);
  return 1;
 }
#endif
}

#ifdef WIN32
static void
run_parent_tests(const char *testfile1, const char *testfile2)
{
 int   fd1,
    fd2;
 HANDLE  h1,
    h2;
 char  exe_path[MAXPGPATH];
 char  cmdline[MAXPGPATH + 100];
 STARTUPINFO si = {.cb = sizeof(si)};
 PROCESS_INFORMATION pi = {0};
 DWORD  exit_code;

 printf("Parent: Opening test files...\n");

 /* Open first file WITH O_CLOEXEC - should NOT be inherited */
 fd1 = open(testfile1, O_RDWR | O_CREAT | O_TRUNC | O_CLOEXEC, 0600);
 if (fd1 < 0)
 {
  fprintf(stderr, "Failed to open %s: %s\n", testfile1, strerror(errno));
  exit(1);
 }

 /* Open second file WITHOUT O_CLOEXEC - should be inherited */
 fd2 = open(testfile2, O_RDWR | O_CREAT | O_TRUNC, 0600);
 if (fd2 < 0)
 {
  fprintf(stderr, "Failed to open %s: %s\n", testfile2, strerror(errno));
  close(fd1);
  exit(1);
 }

 /* Get Windows HANDLEs from file descriptors */
 h1 = (HANDLE) _get_osfhandle(fd1);
 h2 = (HANDLE) _get_osfhandle(fd2);

 if (h1 == INVALID_HANDLE_VALUE || h2 == INVALID_HANDLE_VALUE)
 {
  fprintf(stderr, "Failed to get OS handles\n");
  close(fd1);
  close(fd2);
  exit(1);
 }

 printf("Parent: fd1=%d (O_CLOEXEC) -> HANDLE=%p\n", fd1, h1);
 printf("Parent: fd2=%d (no O_CLOEXEC) -> HANDLE=%p\n", fd2, h2);

 /*
  * Find the actual executable path by removing any arguments from
  * GetCommandLine(), and add our new arguments.
 */

 GetModuleFileName(NULL, exe_path, sizeof(exe_path));
 snprintf(cmdline, sizeof(cmdline), "\"%s\" %p %p", exe_path, h1, h2);

 printf("Parent: Spawning child process...\n");
 printf("Parent: Command line: %s\n", cmdline);

 if (!CreateProcess(NULL, /* application name */
        cmdline, /* command line */
        NULL, /* process security attributes */
        NULL, /* thread security attributes */
        TRUE/* bInheritHandles - CRITICAL! */
        0,  /* creation flags */
        NULL, /* environment */
        NULL, /* current directory */
        &si,  /* startup info */
        &pi)) /* process information */
 {
  fprintf(stderr, "CreateProcess failed: %lu\n", GetLastError());
  close(fd1);
  close(fd2);
  exit(1);
 }

 printf("Parent: Waiting for child process...\n");

 /* Wait for child to complete */
 WaitForSingleObject(pi.hProcess, INFINITE);
 GetExitCodeProcess(pi.hProcess, &exit_code);

 CloseHandle(pi.hProcess);
 CloseHandle(pi.hThread);

 close(fd1);
 close(fd2);

 printf("Parent: Child exit code: %lu\n", exit_code);

 if (exit_code == 0)
 {
  printf("Parent: SUCCESS - O_CLOEXEC behavior verified\n");
 }
 else
 {
  printf("Parent: FAILURE - O_CLOEXEC not working correctly\n");
  exit(1);
 }
}

static void
run_child_tests(const char *handle1_str, const char *handle2_str)
{
 HANDLE  h1,
    h2;
 bool  h1_worked,
    h2_worked;

 /* Parse handle values from hex strings */
 if (sscanf(handle1_str, "%p", &h1) != 1 ||
  sscanf(handle2_str, "%p", &h2) != 1)
 {
  fprintf(stderr, "Child: Failed to parse handle values\n");
  exit(1);
 }

 printf("Child: Received HANDLE1=%p (should fail - O_CLOEXEC)\n", h1);
 printf("Child: Received HANDLE2=%p (should work - no O_CLOEXEC)\n", h2);

 /* Try to write to both handles */
 h1_worked = try_write_to_handle(h1, "HANDLE1");
 h2_worked = try_write_to_handle(h2, "HANDLE2");

 printf("Child: HANDLE1 (O_CLOEXEC): %s\n",
     h1_worked ? "ACCESSIBLE (BAD!)" : "NOT ACCESSIBLE (GOOD!)");
 printf("Child: HANDLE2 (no O_CLOEXEC): %s\n",
     h2_worked ? "ACCESSIBLE (GOOD!)" : "NOT ACCESSIBLE (BAD!)");

 /*
  * For O_CLOEXEC to work correctly, h1 should NOT be accessible (h1_worked
  * == false) and h2 SHOULD be accessible (h2_worked == true).
 */

 if (!h1_worked && h2_worked)
 {
  printf("Child: Test PASSED - O_CLOEXEC working correctly\n");
  exit(0);
 }
 else
 {
  printf("Child: Test FAILED - O_CLOEXEC not working correctly\n");
  exit(1);
 }
}

static bool
try_write_to_handle(HANDLE h, const char *label)
{
 const char *test_data = "test\n";
 DWORD  bytes_written;
 BOOL  result;

 result = WriteFile(h, test_data, strlen(test_data), &bytes_written, NULL);

 if (result && bytes_written == strlen(test_data))
 {
  printf("Child: Successfully wrote to %s\n", label);
  return true;
 }
 else
 {
  printf("Child: Failed to write to %s (error %lu)\n",
      label, GetLastError());
  return false;
 }
}
#endif

Messung V0.5 in Prozent
C=84 H=97 G=90

¤ Dauer der Verarbeitung: 0.15 Sekunden  (vorverarbeitet am  2026-08-08) ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

PVS Prover

Isabelle Prover

NIST Cobol Testsuite

Cephes Mathematical Library

Vienna Development Method

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.






                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Open Source Software

     Quellcodebibliothek
     Eigene Quellcodes
     Fremde Quellcodes
     Suchen

Jenseits des Üblichen ....
    

Besucherstatistik

Besucherstatistik

Statistik
#Sources=141584
#Domains=752002