Skip to content

Commit

Permalink
Merge branch 'master' into racy-tcp-gate
Browse files Browse the repository at this point in the history
  • Loading branch information
larskanis authored Feb 25, 2023
2 parents 9626c79 + cb249b4 commit 10e5b12
Show file tree
Hide file tree
Showing 6 changed files with 139 additions and 47 deletions.
22 changes: 14 additions & 8 deletions .appveyor.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,11 @@ install:
- ps: |
if ($env:RUBYDOWNLOAD -ne $null) {
$(new-object net.webclient).DownloadFile("https://github.com/oneclick/rubyinstaller2/releases/download/rubyinstaller-head/rubyinstaller-head-$env:RUBYDOWNLOAD.exe", "$pwd/ruby-setup.exe")
cmd /c ruby-setup.exe /verysilent /dir=C:/Ruby$env:ruby_version
cmd /c ruby-setup.exe /currentuser /verysilent /dir=C:/Ruby$env:ruby_version
}
- cmd: |
ridk enable
c:/msys64/usr/bin/bash -lc "pacman -S --noconfirm --needed ${MINGW_PACKAGE_PREFIX}-pkgconf ${MINGW_PACKAGE_PREFIX}-libyaml ${MINGW_PACKAGE_PREFIX}-gcc"
- ruby --version
- gem --version
- gem install bundler --conservative
Expand All @@ -18,19 +21,22 @@ install:
{
$(new-object net.webclient).DownloadFile('http://get.enterprisedb.com/postgresql/postgresql-' + $env:PGVERSION + '.exe', 'C:/postgresql-setup.exe')
cmd /c "C:/postgresql-setup.exe" --mode unattended --extract-only 1
$env:PATH = 'C:/Program Files/PostgreSQL/' + $env:PGVER + '/bin;' + $env:PATH
$env:PATH = 'C:/Program Files (x86)/PostgreSQL/' + $env:PGVER + '/bin;' + $env:PATH
} else {
c:/msys64/usr/bin/bash -lc "pacman -S --noconfirm --needed `${MINGW_PACKAGE_PREFIX}-postgresql"
}
$env:PATH = 'C:/Program Files/PostgreSQL/' + $env:PGVER + '/bin;' + $env:PATH
$env:PATH = 'C:/Program Files (x86)/PostgreSQL/' + $env:PGVER + '/bin;' + $env:PATH
- echo %PATH%
- pg_config
build_script:
- bundle exec rake -rdevkit compile --trace
test_script:
- bundle exec rake test PG_DEBUG=0
on_failure:
- find -name mkmf.log | xargs cat
environment:
matrix:
- ruby_version: "head"
RUBYDOWNLOAD: x86
PGVERSION: 10.20-1-windows
PGVER: 10
- ruby_version: "25"
PGVERSION: 9.3.25-1-windows
PGVER: 9.3
- ruby_version: "30-x64"
49 changes: 40 additions & 9 deletions .github/workflows/binary-gems.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
name: Binary gems

on: [push, pull_request]
on:
push:
pull_request:
workflow_dispatch:
schedule:
- cron: "0 5 * * 3" # At 05:00 on Wednesday # https://crontab.guru/#0_5_*_*_3

jobs:
job_build_x64:
Expand All @@ -12,12 +17,13 @@ jobs:
include:
- platform: "x64-mingw-ucrt"
- platform: "x64-mingw32"
- platform: "x86-mingw32"
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v3
- name: Set up Ruby
uses: ruby/setup-ruby@v1
with:
ruby-version: "3.1"
ruby-version: "3.2"
- run: bundle install

- name: Create a dummy cert to satisfy the build
Expand All @@ -31,7 +37,7 @@ jobs:
run: bundle exec rake gem:windows:${{ matrix.platform }}

- name: Upload binary gem
uses: actions/upload-artifact@v2
uses: actions/upload-artifact@v3
with:
name: binary-gem
path: pkg/*.gem
Expand All @@ -43,25 +49,43 @@ jobs:
fail-fast: false
matrix:
include:
- ruby: "3.1"
- os: windows-latest
ruby: "3.2"
platform: "x64-mingw-ucrt"
PGVERSION: 15.1-1-windows-x64
- ruby: "2.5"
- os: windows-latest
ruby: "3.1.3-1"
platform: "x86-mingw32"
PGVERSION: 10.20-1-windows
- os: windows-latest
ruby: "2.5"
platform: "x64-mingw32"
PGVERSION: 10.20-1-windows

runs-on: windows-latest
runs-on: ${{ matrix.os }}
env:
PGVERSION: ${{ matrix.PGVERSION }}
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v3
- name: Set up Ruby
if: matrix.platform != 'x86-mingw32'
uses: ruby/setup-ruby@v1
with:
ruby-version: ${{ matrix.ruby }}

- name: Set up 32 bit x86 Ruby
if: matrix.platform == 'x86-mingw32'
run: |
$(new-object net.webclient).DownloadFile("https://github.com/oneclick/rubyinstaller2/releases/download/RubyInstaller-${{ matrix.ruby }}/rubyinstaller-${{ matrix.ruby }}-x86.exe", "$pwd/ruby-setup.exe")
cmd /c ruby-setup.exe /currentuser /verysilent /dir=C:/Ruby-${{ matrix.ruby }}
echo "c:/ruby-${{ matrix.ruby }}/bin" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append
c:/ruby-${{ matrix.ruby }}/bin/ridk enable
c:/msys64/usr/bin/bash -lc "pacman -S --noconfirm --needed make `${MINGW_PACKAGE_PREFIX}-pkgconf `${MINGW_PACKAGE_PREFIX}-libyaml `${MINGW_PACKAGE_PREFIX}-gcc `${MINGW_PACKAGE_PREFIX}-make"
echo "C:/msys64/$env:MSYSTEM_PREFIX/bin" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append
- name: Download gem from build job
uses: actions/download-artifact@v2
uses: actions/download-artifact@v3
with:
name: binary-gem

Expand All @@ -79,8 +103,15 @@ jobs:
echo "PGUSER=$env:USERNAME" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append
echo "PGPASSWORD=" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append
- run: echo $env:PATH
- run: gem update --system 3.3.26
- run: bundle install
- run: gem install --local pg-*${{ matrix.platform }}.gem --verbose
- name: Run specs
run: ruby -rpg -S rspec -fd spec/**/*_spec.rb

- name: Print logs if job failed
if: ${{ failure() && matrix.os == 'windows-latest' }}
run: |
ridk enable
find "$(ruby -e"puts RbConfig::CONFIG[%q[libdir]]")" -name mkmf.log -print0 | xargs -0 cat
19 changes: 12 additions & 7 deletions .github/workflows/source-gem.yml
Original file line number Diff line number Diff line change
@@ -1,23 +1,28 @@
name: Source gem

on: [push, pull_request]
on:
push:
pull_request:
workflow_dispatch:
schedule:
- cron: "0 5 * * 3" # At 05:00 on Wednesday # https://crontab.guru/#0_5_*_*_3

jobs:
job_build_gem:
name: build
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v3
- name: Set up Ruby
uses: ruby/setup-ruby@v1
with:
ruby-version: "3.1"
ruby-version: "3.2"

- name: Build source gem
run: gem build pg.gemspec

- name: Upload source gem
uses: actions/upload-artifact@v2
uses: actions/upload-artifact@v3
with:
name: source-gem
path: "*.gem"
Expand All @@ -41,7 +46,7 @@ jobs:
ruby: "head"
PGVER: "15"
- os: ubuntu
ruby: "3.1"
ruby: "3.2"
PGVER: "12"
- os: ubuntu
os_ver: "20.04"
Expand All @@ -65,14 +70,14 @@ jobs:
MAKE: make -j2 V=1

steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v3
- name: Set up Ruby
uses: ruby/setup-ruby@v1
with:
ruby-version: ${{ matrix.ruby }}

- name: Download gem from build job
uses: actions/download-artifact@v2
uses: actions/download-artifact@v3
with:
name: source-gem

Expand Down
53 changes: 39 additions & 14 deletions ext/pg_connection.c
Original file line number Diff line number Diff line change
Expand Up @@ -2446,8 +2446,9 @@ pgconn_async_flush(VALUE self)
VALUE socket_io = pgconn_socket_io(self);
events = RB_NUM2INT(pg_rb_io_wait(socket_io, RB_INT2NUM(PG_RUBY_IO_READABLE | PG_RUBY_IO_WRITABLE), Qnil));

if (events & PG_RUBY_IO_READABLE)
if (events & PG_RUBY_IO_READABLE){
pgconn_consume_input(self);
}
}
return Qtrue;
}
Expand Down Expand Up @@ -3126,17 +3127,27 @@ pgconn_async_get_last_result(VALUE self)
* conn.discard_results()
*
* Silently discard any prior query result that application didn't eat.
* This is done prior of Connection#exec and sibling methods and can
* be called explicitly when using the async API.
* This is internally used prior to Connection#exec and sibling methods.
* It doesn't raise an exception on connection errors, but returns +false+ instead.
*
* Returns:
* * +nil+ when the connection is already idle
* * +true+ when some results have been discarded
* * +false+ when a failure occured and the connection was closed
*
*/
static VALUE
pgconn_discard_results(VALUE self)
{
PGconn *conn = pg_get_pgconn(self);
VALUE socket_io;

if( PQtransactionStatus(conn) == PQTRANS_IDLE ) {
return Qnil;
switch( PQtransactionStatus(conn) ) {
case PQTRANS_IDLE:
case PQTRANS_INTRANS:
case PQTRANS_INERROR:
return Qnil;
default:;
}

socket_io = pgconn_socket_io(self);
Expand All @@ -3149,10 +3160,21 @@ pgconn_discard_results(VALUE self)
* To avoid this call pg_rb_io_wait() and PQconsumeInput() without rb_raise().
*/
while( gvl_PQisBusy(conn) ){
pg_rb_io_wait(socket_io, RB_INT2NUM(PG_RUBY_IO_READABLE), Qnil);
if ( PQconsumeInput(conn) == 0 ) {
pgconn_close_socket_io(self);
return Qfalse;
int events;

switch( PQflush(conn) ) {
case 1:
events = RB_NUM2INT(pg_rb_io_wait(socket_io, RB_INT2NUM(PG_RUBY_IO_READABLE | PG_RUBY_IO_WRITABLE), Qnil));
if (events & PG_RUBY_IO_READABLE){
if ( PQconsumeInput(conn) == 0 ) goto error;
}
break;
case 0:
pg_rb_io_wait(socket_io, RB_INT2NUM(PG_RUBY_IO_READABLE), Qnil);
if ( PQconsumeInput(conn) == 0 ) goto error;
break;
default:
goto error;
}
}

Expand All @@ -3162,7 +3184,9 @@ pgconn_discard_results(VALUE self)
status = PQresultStatus(cur);
PQclear(cur);
if (status == PGRES_COPY_IN){
gvl_PQputCopyEnd(conn, "COPY terminated by new PQexec");
while( gvl_PQputCopyEnd(conn, "COPY terminated by new query or discard_results") == 0 ){
pgconn_async_flush(self);
}
}
if (status == PGRES_COPY_OUT){
for(;;) {
Expand All @@ -3171,10 +3195,7 @@ pgconn_discard_results(VALUE self)
if( st == 0 ) {
/* would block -> wait for readable data */
pg_rb_io_wait(socket_io, RB_INT2NUM(PG_RUBY_IO_READABLE), Qnil);
if ( PQconsumeInput(conn) == 0 ) {
pgconn_close_socket_io(self);
return Qfalse;
}
if ( PQconsumeInput(conn) == 0 ) goto error;
} else if( st > 0 ) {
/* some data retrieved -> discard it */
PQfreemem(buffer);
Expand All @@ -3187,6 +3208,10 @@ pgconn_discard_results(VALUE self)
}

return Qtrue;

error:
pgconn_close_socket_io(self);
return Qfalse;
}

/*
Expand Down
2 changes: 1 addition & 1 deletion spec/helpers.rb
Original file line number Diff line number Diff line change
Expand Up @@ -688,7 +688,7 @@ def with_env_vars(**kwargs)
config.filter_run_excluding( :postgresql_12 ) if PG.library_version < 120000
config.filter_run_excluding( :postgresql_14 ) if PG.library_version < 140000
config.filter_run_excluding( :unix_socket ) if RUBY_PLATFORM=~/mingw|mswin/i
config.filter_run_excluding( :scheduler ) if RUBY_VERSION < "3.0" || !Fiber.respond_to?(:scheduler)
config.filter_run_excluding( :scheduler ) if RUBY_VERSION < "3.0" || (RUBY_PLATFORM =~ /mingw|mswin/ && RUBY_VERSION < "3.1") || !Fiber.respond_to?(:scheduler)
config.filter_run_excluding( :scheduler_address_resolve ) if RUBY_VERSION < "3.1"
config.filter_run_excluding( :ipv6 ) if Addrinfo.getaddrinfo("localhost", nil, nil, :STREAM).size < 2

Expand Down
41 changes: 33 additions & 8 deletions spec/pg/connection_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -645,7 +645,7 @@
skip "TcpGateSwitcher transfers wrong data on Truffleruby"
end

run_with_gate(60) do |conn, gate|
run_with_gate(200) do |conn, gate|
conn.setnonblocking(true)

res = nil
Expand Down Expand Up @@ -675,7 +675,7 @@
skip "TcpGateSwitcher transfers wrong data on Truffleruby"
end

run_with_gate(60) do |conn, gate|
run_with_gate(200) do |conn, gate|
conn.setnonblocking(true)

gate.stop
Expand Down Expand Up @@ -1517,12 +1517,37 @@
expect( conn.connect_poll ).to eq( PG::PGRES_POLLING_FAILED )
end

it "discards previous results at #discard_results" do
@conn.send_query( "select 1" )
@conn.discard_results
@conn.send_query( "select 41 as one" )
res = @conn.get_last_result
expect( res.to_a ).to eq( [{ 'one' => '41' }] )
describe "#discard_results" do

it "discards previous results" do
@conn.send_query( "select 1" )
expect( @conn.discard_results ).to eq( true )
@conn.send_query( "select 41 as one" )
res = @conn.get_last_result
expect( res.to_a ).to eq( [{ 'one' => '41' }] )
end

it "returns nil when in idle state", :without_transaction do
expect( @conn.discard_results ).to eq( nil )

@conn.transaction do
expect( @conn.discard_results ).to eq( nil )
end

@conn.transaction do
@conn.send_query( "WRONG COMMAND" )
@conn.get_result
@conn.get_result

expect( @conn.discard_results ).to be_nil
end
end

it "returns false on connection failures" do
conn = PG.connect(@conninfo)
conn.send_query("select pg_terminate_backend(pg_backend_pid());")
expect( conn.discard_results ).to eq( false )
end
end

it "discards previous results (if any) before waiting on #exec" do
Expand Down

0 comments on commit 10e5b12

Please sign in to comment.