/* gcc -I/usr/include/postgresql -L/usr/lib/postgresql/12/lib -o pq-test pq-test.c -lpq */ #include #include #include #include #include #include #include #include #include #include /* Sample output: ** pottmi@ubuntu ~/src ** % ./pq-test ** [37095] with sslmode=require: ** [37095] Calling New() ** [37097] Calling Exec() ** [37098] Calling Exec() ** [37098] Error in results: PGRES_FATAL_ERROR ** ** [37095] with sslmode=disable: ** [37095] Calling New() ** [37100] Calling Exec() ** [37101] Calling Exec() ** pottmi@ubuntu ~/src ** ** pottmi@ubuntu ~/src ** % uname -a ** Linux ubuntu 5.13.0-40-generic #45~20.04.1-Ubuntu SMP Mon Apr 4 09:38:31 UTC 2022 x86_64 x86_64 x86_64 GNU/Linux ** pottmi@ubuntu ~/src ** % cat /etc/debian_version ** bullseye/sid ** pottmi@ubuntu ~/src */ char *connectwillfail = "postgresql://kicktest:changeme@localhost:5432/kicktest?sslmode=require"; char *connectwillsucceed = "postgresql://kicktest:changeme@localhost:5432/kicktest?sslmode=disable"; char *sql = "select count(*) from information_schema.tables where table_schema = 'public'"; PGconn *New(const char *connectstr) { PGconn *con; printf("[%d] Calling New()\n", getpid()); con = PQconnectdb(connectstr); if (PQstatus(con) != CONNECTION_OK) { printf("[%d] could not connect to %s because %s\n", getpid(), connectstr, PQerrorMessage(con)); } return(con); } void Exec(PGconn *con, char *sql) { printf("[%d] Calling Exec()\n", getpid()); PGresult *result; ExecStatusType status; result = PQexec(con, sql); status = PQresultStatus(result); if (status != PGRES_TUPLES_OK) { printf("[%d] Error in results: %s\n", getpid(), PQresStatus(status)); } PQclear(result); } void runit(const char *connectstring) { int status; // Allocate connection in parent, but we will not use it in the parent process. PGconn *con = New(connectstring); int pid = fork(); if (pid == 0) // Child process { // use connection in first child. Exec(con, sql); exit(0); } else if (pid > 0) // Parent process { int pidrtn = wait(&status); } else // if (pid < 0) // Error { printf("[%d] Failed to fork! (errno=%d)\n", pid, errno); exit(1); } pid = fork(); if (pid == 0) // Child process { // use connection in a second child. Exec(con, sql); exit(0); } else if (pid > 0) // Parent process { int pidrtn = wait(&status); } else // if (pid < 0) // Error { printf("[%d] Failed to fork! (errno=%d)\n", pid, errno); exit(1); } PQfinish(con); } void main(void) { printf("[%d] with sslmode=require:\n", getpid()); runit(connectwillfail); printf("\n[%d] with sslmode=disable:\n", getpid()); runit(connectwillsucceed); }